Views in Doctrine ORM - doctrine

I encountered a problem dealing with views in Doctrine.
I have the following view in my database:
$q = Doctrine_Query::create()
->select('c.id, c.name, m.id, m.name, m.status,
m.modified, m.entered, m.accountid')
->from('Category c')
->leftJoin('c.Mailing m');
$view = new Doctrine_View($q, 'view_mailings');
$q->execute(array(), Doctrine::HYDRATE_ARRAY);
The result comprises of all records. However I need to fetch a subset
based on different value for accountid and ordered by different
columns. How can I achieve this?
Thanks for your help.

A different solution could be creating a schema for the view inside config/doctrine/ like this:
objective:
tableName: objective
columns:
id:
type: integer
zone:
type: string(50)
province:
type: string(30)
city:
type: string(100)
population:
type: integer
city_obj_id:
type: integer
clinic_number:
type: integer
clinic_obj:
type: integer
comments:
type: string(255)
and then put a objective_view.sql inside data/sql/ like this:
DROP VIEW IF EXISTS objective;
DROP TABLE IF EXISTS objective;
CREATE VIEW objective AS
SELECT
c.id as id,
z.name as zone,
p.name as province,
c.name as city,
cs.amount as population,
co.id as city_obj_id,
co.clinic_num as clinic_number,
co.clinic_obj as clinic_obj,
co.comments as comments
FROM
city c left join city_objective co on co.city_id = c.id
left join city_census cs on (cs.city_id = c.id and cs.year = 2009)
left join province p on p.id = c.province_id
left join zone z on z.id = p.zone_id;
In this way the objective table will get populated with updated data and you can execute query on it to get relevant info with ease.

You are just executing the query $q, without using the view you have created.

Related

union and eager loading with eloquent in laravel

I have a table Uuids which has a morph relation with dealers, masterdealers, admins and customers table. I need to get the email addresses from all the above mentioned user types tables along with their uuids from the uuids table. i'm using union to get all the emails from dealers, masterdealers, admins and customers table but I want to somehow eagerload their uuids too.
my desired output would be something like this :
{
email: 1#example.com
uuid: 1
}, {
email: 2#example.com
uuid: 5
}, {
email: 3#example.com
uuid: 11
}
I have tried:
DB::select("SELECT email FROM customers
UNION SELECT email FROM dealers
UNION SELECT email FROM masterdealers
UNION SELECT email FROM admins");
and it gives me all the emails from these 4 tables.
You need to join your morph table with in order to get uuids for your different models
SELECT u.uuid,c.email
FROM customers c
JOIN Uuids u ON c.id = u.some_mapped_col AND u.some_morph_col = 'Model Name'
UNION
SELECT u.uuid,d.email FROM dealers d
JOIN Uuids u ON d.id = u.some_mapped_col AND u.some_morph_col = 'Model Name'
UNION
SELECT u.uuid, m.email FROM masterdealers m
JOIN Uuids u ON m.id = u.some_mapped_col AND u.some_morph_col = 'Model Name'
UNION
SELECT u.uuid, a.email FROM admins a
JOIN Uuids u ON a.id = u.some_mapped_col AND u.some_morph_col = 'Model Name'
Also to run raw queries in laravel you might need DB::raw('.....')

joining multiple tables, then grouping and suming in linq

How could I get this SQL query right in LINQ?
SQL query:
select c.Name, sum(t.value)
from Categories c
join Items i on c.Id = i.CategoryId
join Transactions t on t.ItemId = i.Id
where datepart(YEAR, t.CreatedTime) = 2016
and datepart(MONTH, t.CreatedTime) = 2
group by c.Name
I've tried to do the same in LINQ and got this:
var query = from cat in _context.Categories
join item in _context.Items on cat.Id equals item.CategoryId
join trans in _context.Transactions on item.Id equals trans.ItemId
where trans.CreatedTime.Month == e.RowIndex && trans.CreatedTime.Year == 2016
group new { cat.Name, trans.Value } by cat.Name into g
select new
{
Value = g.Sum(entry => entry.Value)
};
But it seems to be totally wrong, besides not giving me back the category names, it returns wrong values for the sums as well.
I have three tables:
Categories with columns Id and Name
Items with columns Id, Name, CategoryId, LastValue, IsIncome,
Transactions with columns Id, ItemId, Value, CreatedTime, IsIncome

LINQ Select Row with Max date per group

I want to return all the values from my "Categories" table and join that to my "CategorySelections" table to display all the categories and whether the specified user selected them or not.
A complication (which I don't know how to deal with in LINQ) is that the user could have changed his selection/deselection of a particular category over time...each change would have logged in the "CategorySelections" table with a date stamp.
I am after the last selection status.
The following SQL query does what I want:
SELECT cs.UserId, c.CategoryId, m.MaxDate, cs.IsSelected
FROM [myDB].[dbo].[Categories] c
LEFT JOIN [myDB].[dbo].[CategorySelections] cs
ON c.CategoryID = cs.CategoryID AND cs.UserID = 7
INNER JOIN
(
SELECT UserId, CategoryId, Max(CreatedOn) as MaxDate
FROM [myDB].[dbo].[CategorySelections]
GROUP BY UserId, CategoryId
) m
ON cs.UserID = m.UserID AND cs.CategoryID = m.CategoryID AND cs.CreatedOn = m.MaxDate
ORDER BY cs.CategoryI
I need some help getting this done in LINQ.
Below is my attempt, which returns all the selections instead of just the last per category.
var query = from c in db.Category
join cs in db.CategorySelection.Where(x => x.UserID == WebSecurity.CurrentUserId)
on c.CategoryID equals cs.CategoryID into JoinedCategory
from cs in JoinedCategory.DefaultIfEmpty()
select new Selection() { CategoryID = c.CategoryID, CategoryName = c.CategoryName ,IsSelected = cs != null ? cs.IsSelected : false }
I am working in MVC; the "new Selection()" refers to my Model
You may add WHERE statement:
where cs.CreatedOn == CategorySelections.Where(t => t.CategoryId == cs.CategoryId).Max(r => r.CreatedOn)

translate raw MySQL into Doctrine 1.2

I'm having a heck of a time translating the following raw MySQL query, which has been tested and works very well, into doctrine 1.2:
SELECT
r.name AS regionname,
s.name AS statename
FROM
job j
LEFT JOIN
community c ON c.id = j.community_id
LEFT JOIN
state s ON s.id = c.state_id
LEFT JOIN
region r ON r.id = s.region_id
WHERE
r.id = 1
This does not work:
$q = Doctrine_Query::create()
->select('r.name AS regionname', 's.name AS statename')
->from('job j')
->leftJoin('community c ON c.id = j.community_id')
->leftJoin('state s ON s.id = c.state_id')
->leftJoin('region r ON r.id = s.region_id')
->where('r.id = 1')
->execute();
Here's my db structure, if it is useful:
job:
columns:
id
community_id
relations:
community: local_key: community_id, foreign_key: id, foreignAlias: Communitys
community:
columns:
id
state_id
relations:
state: local_key: state_id, foreign_key: id, foreignAlias: States
state:
columns:
id
name
region_id
relations:
region: local_key: region_id, foreign_key: id, foreignAlias: Regions
region:
columns:
id
name
I have noticed the same thing as well. Doing joins in Doctrine 1.2 is a little bit different from mysql. To do a join, you have to take advantage of the relationships that Doctrine creates in each component in your case the job class.
You can check the job's base class for these relationships I am talking about. In the setup method, they look like this for example for a community foreign key id in the job table:
$this->hasOne('community as Communitys', array(
'local' => 'community_id',
'foreign' => 'id'));
Back to your question, to do a join you have to reference the alias of the table where the foreign key belongs to. For example if you want to join on the community table with the alias Community:
->leftJoin('j.Community')
instead of
community c ON c.id = j.community_id
Notice that I didn't say join on id because in Doctrine 1.2 that is implied already. You can however choose to join on something else.
Likewise if tables you have previously joined to need to be joined to other tables they have foreign keys to you have to
1.use their alias in the current queryand
2.reference the component as stated in THEIR base class as well.
So you said that you want to join community to states in the current query the way you should do it is
// join job and community first
->from('job j')
->leftJoin('j.Community c')
// join community to state since they are the ones that are related
->leftjoin('c.States s')
From here I hope you can see the pattern. At the end of the day if you look at it the idea of joining is still the same with raw sql, the only difference is the syntax:
SQL syntax:
LEFT JOIN
community c ON c.id = j.community_id
DQL syntax:
->leftJoin('j.Community c')
Anyway to answer your question, here is how the join should somewhat be done:
$q = Doctrine_Query::create()
->select('*')
->from('job j')
->leftJoin('j.Community c')
->leftJoin('c.State s')
->leftJoin('s.Region r')
->where('r.id = 1')
->execute();

Linq query help

I'm attempting to write a linq query which uses several tables of related data and have gotten stuck.
The expected result: I need to return the three most populous metropolitan areas per region by population descending.
tables w/sample data:
MetroAreas -- ID, Name
2, Greater New York
Cities -- ID, Name, StateID
1293912, New York City, 10
CityPopulations -- ID, CityID, CensusYear, Population
20, 1293912, 2008, 123456789
21, 1293912, 2007, 123454321
MetroAreaCities -- ID, CityID, MetroAreaID
1, 1293912, 2
States -- ID, Name, RegionID
10, New York, 5
Regions -- ID, Name
5, Northeast
I start with the metro areas. Join the MetroAreaCities to get city IDs. Join Cities to get state IDs. Join States to get the region ID. Join regions so I can filter with a where. I get stuck when I try to include CityPopulations. I only want the three most populous metro areas for a given region. Doing a simple join on the cityPopulations returns a record per year.
(Here's what I have so far, this query was written for SubSonic 3):
return from p in GeoMetroArea.All()
join q in GeoMetroAreaCity.All() on p.ID equals q.MetroAreaID
join r in GeoCity.All() on q.CityID equals r.ID
join s in GeoState.All() on r.StateID equals s.ID
join t in GeoRegion.All() on s.RegionID equals t.ID
where t.ID == regionObjectPassedToMethod.ID
select p;
Can anyone help me with this query or point me in the right direction? Thank you very very much.
I haven't compiled it, but this should get you close:
var regionID = 5;
var year = (from c in GeoCityPopulation.All()
select c.CensusYear
).Max();
var metros =
// States in Region
from s in GeoStateAll()
where s.RegionID == regionID
// Cities in State
join c in GeoCity.All() on s.CityID equals c.ID
// Metro Area for City
join mc in GeoMetroAreaCity.All() on c.ID equals mc.CityID
// Population for City
join cp in GeoCityPopulation.All() on c.ID equals cp.CityID
where cp.CensusYear = year
// Group the population values by Metro Area
group cp.Population by mc.MetroAreaID into g
select new
{
MetroID = g.Key, // Key = mc.MetroAreaID
Population = g.Sum() // g = seq. of Population values
} into mg
// Metro for MetroID
join m in GeoMetroArea.All() on mg.MetroID equals m.ID
select new { m.Name, mg.Population };

Resources