Need to get room type wise female and male count, below is my query
(SELECT WARD,ROOMTYPE ,FEMALE,MALE
FROM
(SELECT NS.WARD,RC.ROOMTYPE,(DECODE(IP.GENDER,'F',COUNT(IP.HNO)))FEMALE,(DECODE(IP.GENDER,'M',COUNT(IP.HNO)))MALE FROM BEDSHIFT R,BED B,NURSTATION NS,PATIENTS IP,ROOMTYPE RT,ROOMCATEGORY RC
WHERE R.BD_CODE=B.BD_CODE AND B.NS_CODE=NS.NS_CODE AND R.IP_NO=IP.IP_NO AND R.RMC_OCCUPBY='B'
AND B.RT_CODE=RT.RT_CODE AND RT.RC_CODE=RC.RC_CODE
AND IP.IPC_STATUS IS NULL AND R.RMC_RELESETYPE IS NULL GROUP BY RC.ROOMTYPE,NS.WARD,IP.GENDER
UNION ALL
SELECT NS.WARD,RC.ROOMTYPE,(DECODE(IP.GENDER,'F',COUNT(IP.HNO)))FEMALE,(DECODE(IP.GENDER,'M',COUNT(IP.HNO)))MALE FROM PATIENTS IP,BED BD,NURSTATION NS,ROOMTYPE RT,ROOMCATEGORY RC
WHERE IP.BD_CODE=BD.BD_CODE
AND BD.RT_CODE=RT.RT_CODE AND RT.RC_CODE=RC.RC_CODE
AND BD.NS_CODE=NS.NS_CODE AND IP.IPC_STATUS IS NULL GROUP BY RC.ROOMTYPE,NS.WARD,IP.GENDER)
T
GROUP BY FEMALE,MALE,WARD,ROOMTYPE) ORDER BY WARD
returns below
need to get it as
Group only once and sum the males and females:
SELECT WARD, ROOMTYPE, sum(FEMALE), sum(MALE)
FROM (SELECT NS.WARD,
RC.ROOMTYPE,
IP.GENDER, 'F', COUNT(IP.HNO))) FEMALE,
IP.GENDER, 'M', COUNT(IP.HNO))) MALE
FROM BEDSHIFT R,
BED B,
NURSTATION NS,
PATIENTS IP,
ROOMTYPE RT,
ROOMCATEGORY RC
WHERE R.BD_CODE = B.BD_CODE
AND B.NS_CODE = NS.NS_CODE
AND R.IP_NO = IP.IP_NO
AND R.RMC_OCCUPBY = 'B'
AND B.RT_CODE = RT.RT_CODE
AND RT.RC_CODE = RC.RC_CODE
AND IP.IPC_STATUS IS NULL
AND R.RMC_RELESETYPE IS NULL
UNION ALL
SELECT NS.WARD,
RC.ROOMTYPE,
(DECODE(IP.GENDER, 'F', COUNT(IP.HNO))) FEMALE,
(DECODE(IP.GENDER, 'M', COUNT(IP.HNO))) MALE
FROM PATIENTS IP,
BED BD,
NURSTATION NS,
ROOMTYPE RT,
ROOMCATEGORY RC
WHERE IP.BD_CODE = BD.BD_CODE
AND BD.RT_CODE = RT.RT_CODE
AND RT.RC_CODE = RC.RC_CODE
AND BD.NS_CODE = NS.NS_CODE
AND IP.IPC_STATUS IS NULL) T
GROUP BY WARD, ROOMTYPE
ORDER BY WARD
This way the query should be faster, than grouping three times, or even fourtimes. You could also use subqueries for males and females, which could be even faster without grouping at all (without seeing the schema, I wouldn't give you the query).
change first line
(SELECT WARD,ROOMTYPE ,SUM(FEMALE) AS FEMALE, SUM(MALE) AS MALE
and last line
GROUP BY WARD,ROOMTYPE) ORDER BY WARD,ROOMTYPE
Related
I have the following data set for a movie database:
Ratings: UserID, MovieID, Rating :: Movies: MovieID, Title :: Users: UserID, Gender, Age
Now I have to JOIN the above 3 datasets and determine which movie has the highest rating among females and lowest rating among males, and vice versa.
I have done the JOIN:
myusers = LOAD '/user/cloudera/movies/input/users.dat'
USING PigStorage(':')
AS (user:int, n1, gender:chararray, n2, age:int);
ratings = LOAD '/user/cloudera/movies/input/ratings.dat'
USING PigStorage(':')
AS (user:int, n1, movie:int, n2, rating:int);
movies = LOAD '/user/cloudera/movies/input/movies.dat'
USING PigStorage(':')
AS (movie:int,n1,title:chararray);
data = JOIN ratings BY user, myusers BY user;
data2= JOIN data BY ratings::movie, movies BY movie;
But after this I am running into many issues such as "ERROR 0: Scalar has more than one row in the output" when I try to print columns from data2. Any ideas to help me accomplish this task?
After the following step
data = JOIN ratings BY user, myusers BY user;
Create two datasets one for male and another for female by using gender as the filter.Order the dataset and get the max and min for both the datasets.
male = FILTER data by gender == 'M'; -- Use the gender value for male
female = FILTER data by gender == 'F';
m_max = LIMIT (ORDER male by rating DESC) 1;
f_max = LIMIT (ORDER female by rating DESC) 1;
m_min = LIMIT (ORDER male by rating ASC) 1;
f_min = LIMIT (ORDER female by rating ASC) 1;
I'm trying to display only the largest group in this group by statement;
SELECT COUNT(type) AS booking, type FROM booking b, room r WHERE r.rno = b.rno AND r.hno = b.hno GROUP BY type;
I modified it so we get this query response now you can see group double is larger then family.
BOOKING TYPE
5 double
2 family
I know there is a HAVING keyword you can add in order display only a count compared to a number so I could do COUNT(type) HAVING > 2 or similar but that's not very dynamic and that would only work in this instance because I know the two amounts.
ORDER BY COUNT(type) DESC LIMIT 1
There isn't a having statement that does this. But you can use rownum with a subquery:
select t.*
from (SELECT COUNT(type) AS booking, type
FROM booking b join
room r
on r.rno = b.rno AND r.hno = b.hno
GROUP BY type
order by count(type) desc
) t
where rownum = 1;
Just order your query..
order by booking desc
regards
TRY this
SELECT COUNT(type) AS booking, type FROM booking b, room r WHERE r.rno = b.rno AND r.hno = b.hno ORDER BY type DESC LIMIT 1
I've to query from two tables and want one result.. how can i join these two queries?
First query is querying from two tables and the second one is only from one.
select pt.id,pt.promorow,pt.promocolumn,pt.type,pt.image,pt.style,pt.quota_allowed,ptc.text,pq.quota_left
from promotables pt,promogroups pg ,promotablecontents ptc ,promoquotas pq where pt.id_promogroup = 1 and ptc.country ='049' and ptc.id_promotable = pt.id and pt.id_promogroup = pg.id and pq.id_promotable = pt.id order by pt.promorow,pt.promocolumn
select pt.id,pt.promorow,pt.promocolumn,pt.type,pt.image,pt.style,pt.quota_allowed from promotables pt where pt.type='heading'
Use UNION or UNION ALL. As long as you have the same number of columns and they are compatible types that should do what you want.
SELECT pt.id, pt.promorow, pt.promocolumn, pt.type, pt.image, pt.style, pt.quota_allowed, ptc.text, pq.quota_left
FROM promotables pt, promogroups pg, promotablecontents ptc, promoquotas pq
WHERE pt.id_promogroup = 1
AND ptc.country ='049'
AND ptc.id_promotable = pt.id
AND pt.id_promogroup = pg.id
AND pq.id_promotable = pt.id
UNION
SELECT pt.id, pt.promorow, pt.promocolumn, pt.type, pt.image, pt.style, pt.quota_allowed, NULL, NULL
FROM promotables pt
WHERE pt.type='heading'
ORDER BY 2, 3
If you want to display duplicates (e.g identical rows coming from both queries), use UNION ALL
Imagine to have a table defined as
CREATE TABLE [dbo].[Price](
[ID] [int] NOT NULL,
[StartDate] [datetime] NOT NULL,
[Price] [int] NOT NULL
)
where ID is the identifier of an action having a certain Price. This price can be updated if necessary by adding a new line with the same ID, different Price, and a more recent date.
So with a set of a data like
ID StartDate Price
1 01/01/2009 10
1 01/01/2010 20
2 01/01/2009 10
2 01/01/2010 20
How to obtain a set like the following?
1 01/01/2010 20
2 01/01/2010 20
In SQL, there are several ways to say it. Here's one that uses a subquery:
SELECT *
FROM Price p
WHERE NOT EXISTS (
SELECT *
FROM Price
WHERE ID = p.ID
AND StartDate > p.StartDate
)
This translates fairly trivially to LINQ:
var q = from p in ctx.Price
where !(from pp in ctx.Price
where pp.ID == p.ID
&& pp.StartDate > p.StartDate
select pp
).Any()
select p;
Or should I say, I think it does. I'm not in front VS right now, so I can't verify that this is correct, or that LINQ will be able to convert it to SQL.
Minor quibble: Don't use the name ID to store a non-unique value (the type, in this case). It's confusing.
Assuming ID & StartDate will be unique:
SELECT p.ID, p.StartDate, p.Price
FROM Price p
JOIN
(
SELECT ID, MAX(StartDate) AS LatestDate
FROM Price
GROUP BY ID
) p2 ON p.ID = p2.ID AND p.StartDate = p2.LatestDate
Since you tagged your question with LINQ to SQL, here is an LINQ query to express what you want:
from price in db.Prices
group price by price.Id into group
let maxDateInGroup = group.Max(g => g.StartDate)
let maxDatePrice = group.First(g => g.StartDate == maxDateInGroup)
select
{
Id = group.Key,
StartDate = maxDatePrice.StartDate,
Price = maxDatePrice.Price
};
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 };