I have two tables in SQL Server (I removed many rows, but it should not affect the result):
[dbo].[Order]:
CaseId Gender
-----------------
698 Female
694 Male
676 Female
659 Male
[dbo].[Plimplan]:
OrderID CaseID InfoID
--------------------------------------------
33425999 698 BBBBBE
33425984 694 AAAAAS
33425984 694 DSSSAS
33425609 694 BBBBBA
33425270 676 AAAAAA
33424973 676 AAAAAD
33424716 676 SASSAS
33424704 676 AAAAAA
33424500 676 BBBBBE
33424340 659 AAAAAA
33424281 659 BBBBBD
and I want to obtain the following one:
[dbo].[Plimplan]:
OrderID CaseID InfoID Gender
----------------------------------------------------
33425984 694 AAAAAS Male
33425270 676 AAAAAA Female
33424340 659 AAAAAA Male
Let's forget the join. I can remove undesired rows from [dbo].[Order] with this:
SELECT TOP (100) MAX (OrderID) AS [OrderID]
,MAX (CaseID) AS [CaseID]
,MAX (InfoID) AS [InfoID]
/*,[Gender]*/
FROM [dbo].[Plimplan] as Plimpl
/* INNER JOIN [dbo].[Order] as Ord
ON Plimpl.CaseID = Ord.CaseID */
WHERE [InfoID] NOT LIKE 'BBBBB%'
and CaseID < 700
and CaseID > 600
GROUP BY (CaseID)
order by CaseID desc
But if I remove the comments to complete the join, I get this error:
Msg 209, Level 16, State 1, Line 3
Ambiguous column name 'CaseID'.
Use aliases. The error you are getting is due to both tables in the join having a CaseID column. SQL Server is telling you that it can't figure out which one you are trying to select.
SELECT TOP 100
MAX (Plimpl.OrderID) AS [OrderID]
MAX (Plimpl.CaseID) AS [CaseID]
MAX (Plimpl.InfoID) AS [InfoID]
FROM [dbo].[Plimplan] AS Plimpl
INNER JOIN [dbo].[Order] AS Ord
ON Plimpl.CaseID = Ord.CaseID
WHERE
Plimpl.[InfoID] NOT LIKE 'BBBBB%' AND
Plimpl.CaseID < 700 AND
Plimpl.CaseID > 600
GROUP BY
Plimpl.CaseID
ORDER BY
Plimpl.CaseID DESC;
You had at one point apparently been selecting the Gender column from the Order table, but it makes no sense to do this with your use of GROUP BY.
You're getting the error when you uncomment the JOIN statement right?
Use Aliases
SELECT TOP (100) MAX (OrderID) AS [OrderID]
,MAX (CaseID) AS [CaseID]
,MAX (InfoID) AS [InfoID]
/*,[Gender]*/
FROM [dbo].[Plimplan] as Plimpl
INNER JOIN [dbo].[Order] as Ord
ON Plimpl.CaseID = Ord.CaseID
WHERE [InfoID] NOT LIKE 'BBBBB%'
and Plimpl.CaseID < 700
and Plimpl.CaseID > 600
GROUP BY Plimpl.CaseID
order by Plimpl.CaseID desc
Related
I have the following query:
SELECT
g.Gender,
a.AgeGroup,
count(*) as Count
FROM
client c
INNER JOIN AgeGroup a
ON c.age BETWEEN a.StartRange AND a.EndRange
INNER JOIN Gender G on
C.GenderID = G.GenderID
group by
g.Gender,
a.AgeGroup
order by AgeGroup, Gender
which gives the following results:
Gender AgeGroup Count
Male <=25 4
Unknown <=25 2
Female >35 2223
Male >35 6997
Transgender >35 43
Unknown >35 2
Female 26-35 413
Male 26-35 590
Transgender 26-35 5
What I'm needing to try and do though is convert the Gender column to column headers and include totals.
AgeGroup Male Female Trans Unknown Total
<= 25: 4 0 0 2 6
26 - 35: 590 413 5 0 1008
> 35: 6997 2223 43 2 9265
Total: 7591 2636 48 4 10279
I've got this far:
SELECT *
FROM (
SELECT
g.Gender as [Gender],
a.AgeGroup
FROM
client c
INNER JOIN AgeGroup a
ON c.age BETWEEN a.StartRange AND a.EndRange
INNER JOIN Gender G on
C.GenderID = G.GenderID
) as s
PIVOT
(
COUNT(Gender)
FOR [Gender] IN (Male,Female,Transgender,Unknown)
)AS pvt
which returns this:
AgeGroup Male Female Transgender Unknown
<=25 4 0 0 2
26-35 590 413 5 0
>35 6997 2223 43 2
But I don't have the totals.
Is there a way I can do this?
Try this ..
SELECT *,
(select sum(v)
from
(values(male),
(female),
(transgender),
(unknown))
as val(v)) as total
FROM (
SELECT
g.Gender as [Gender],
a.AgeGroup
FROM
client c
INNER JOIN AgeGroup a
ON c.age BETWEEN a.StartRange AND a.EndRange
INNER JOIN Gender G on
C.GenderID = G.GenderID
) as s
PIVOT
(
COUNT(Gender)
FOR [Gender] IN (Male,Female,Transgender,Unknown)
)AS pvt
For updated requirement:
i recommend putting entire table into Some temp table for readabilty and do this
So your above query would go like this
SELECT *,
(select sum(v)
from
(values(male),
(female),
(transgender),
(unknown))
as val(v)) as total
into #temp
from
rest of pivot query
and then do grouping for total
select
case when grouping(agegroup)=1 then 'total' else agegroup end agegroup,
sum(male) as male,
sum(female) as 'female',
sum(trans) as 'trans',
sum(unknown) as 'unknown',
sum(total) as 'Total'
from #temp
group by
grouping sets
(
(agegroup),
()
)
I'm trying to group a set of data and for some of the fields I need to select a specific value based on the ttype, for example I have the following rows:
caseid age iss gcs ttype
00170 64 25 17 Transfer Out
00170 64 27 15 Transfer In
00201 24 14 40 Transfer In
If a caseID has ttype 'Transfer Out' I want to use the ISS and GCS values from this row, otherwise use the values from the 'Transfer In' row.
My desired output based on the above example would be:
caseid age iss gcs
00170 64 25 17
00201 24 14 40
My current select statement is:
select caseid, max(age), max(iss), max(gcs)
from Table1
group by caseid
Which I know is incorrect but how do I specify the values for ISS and GCS from a specific row?
Thanks
Edit - I will not always need to select from Row1, table below with expanded data:
caseid age iss gcs los ttype disdate
170 64 25 17 5 Transfer Out 2014-01-02 00:00:00.000
170 64 27 15 1 Transfer In 2014-01-04 00:00:00.000
201 24 14 40 4 Transfer In 2014-01-04 00:00:00.000
In this case, I want the max age and the ISS and GCS figure for row1 as before but I need to sum the LOS and select the disdate for row 2 (ie the latest date), so my output would be:
caseid age iss gcs los disdate
170 64 25 17 6 2014-01-04
201 24 14 40 4 2014-01-04
Is this possible?
You can use a CTE and ROW_NUMBER + Over-clause (edited acc. to your updated question):
WITH CTE AS
(
SELECT caseid, age, iss, gcs, los, ttype, disdate,
SumLos = SUM(los) OVER (PARTITION BY caseid),
LatestDisDate = MAX(disdate) OVER (PARTITION BY caseid),
rn = ROW_NUMBER() OVER (PARTITION BY caseid
ORDER BY CASE WHEN ttype = 'Transfer Out'
THEN 0 ELSE 1 END ASC, disdate ASC)
FROM dbo.Table1
)
SELECT caseid, age, iss, gcs, los = SumLos, disdate = LatestDisDate
FROM CTE
WHERE rn = 1
Demo
I think this is what you need -
;WITH CTE AS
(
SELECT case_id, age,iss,gcs, ROW_NUMBER () over (PARTITION BY ttype order by gcs DESC) Rn
from YOUR_TABLE_NAME
)
SELECT case_id,age,iss,gcs
from CTE where Rn =1
I have a table like this
PkReferencesID FkReferencesID DocID FKHRSEmployeeID AssignedDate AssignedTime FKActivityID
40855 NULL 8530 13 13920625 0829 1
40856 40855 8530 438 13920625 0829 1
40857 40856 8530 13 13920625 0829 2
40858 40857 8530 438 13920625 0830 1
40859 40858 8530 NULL 13920625 0830 1
NULL NULL NULL NULL NULL NULL NULL
How i can select rows with DocID = 8530 and FKActivityID = 1 and Maximum AssignedDate and Maximum AssignedTime for per FKHRSEmployeeID?
Note:the result should be one row for per FKHRSEmployeeID
Any help would be appriciated. Thanks
The result must be like this
PkReferencesID FkReferencesID DocID FKHRSEmployeeID AssignedDate AssignedTime FKActivityID
40855 NULL 8530 13 13920625 0829 1
40858 40857 8530 438 13920625 0830 1
The easiest way to do this is with row_number():
select t.*
from (select t.*,
row_number() over (partition by FKHRSEmployeeID
order by AssignedDate desc, AssignedTime desc
) as seqnum
from t
where DocID = 8530 and FKActivityID = 1
) t
where seqnum = 1
Query 2 will retrieve the information you're asking for:
Query1: This query gets the maximum assigned date/time for each employee.
SELECT FKHRSEmployeeID, MAX(AssignedDate & AssignedTime)
FROM Table
WHERE T.DocID=8530
AND T.FKActivityID=1
GROUP BY FKHRSEmployeeID;
Query2: This query uses the former one to retrieve only the matching records.
SELECT T.*
FROM Table AS T
INNER JOIN Query1 AS Q
ON (T.Date=LEFT(Q.MaxDateTime,8))
AND (T.Time=RIGHT(Q.MaxDateTime,4))
AND (T.FKHRSEmployeeID=Q.FKHRSEmployeeID)
WHERE T.DocID=8530
AND T.FKActivityID=1;
This query by itself doesn't guarantee you'll only get one record per employee, unless the combination FKHRSEmployeeID/AssignedDate/AssignedTime is unique in the table. You can ensure this by creating a unique index based on those columns.
I'm using SQL Server 2008, I want select random row record, and the total number of record is depend on another table's column value, how to do this?
My SQL statement is something like this, but wrong..
select top b.number a.name, a.link_id
from A a
left join B b on b.link_id = a.link_id
order by newid()
Here are my tables and the expected result.
Table A:
name link_id
james 100
albert 100
susan 100
simon 101
tom 101
fion 101
Table B:
link_id number
100 2
101 1
Expected result:
when run 1st time, result may be:
name link_id
james 100
susan 100
fion 101
2nd time result may be:
albert 100
susan 100
simon 101
3rd time could be:
james 100
albert 100
fion 101
Explaination
Refer to table B, link_id: 100, number: 2
meaning that Table A should select out 2 random record for link_id = 100
and need to select 1 random record for link_id=101
You can use the ROW_NUMBER() function:
SELECT A.name, A.link_id
FROM(
SELECT name,link_id, ROW_NUMBER()OVER(PARTITION BY link_id ORDER BY NEWID()) rn
FROM dbo.tblA
) AS A
JOIN dbo.tblB AS B
ON A.link_id = B.link_id
WHERE A.rn <= B.number;
Here is a SqlFiddle to show this in action: http://sqlfiddle.com/#!3/92eac/2
Try this:
SELECT a.*
FROM b
CROSS APPLY
(
SELECT TOP (b.number) a.*
FROM a
WHERE a.link_id = b.link_id
ORDER BY
NEWID()
) a
Also see: SQLFiddle
i have a table with values like this,
i want to group by cusotmer name where as sum of the local amount should exceed 50000 else i need to delete those records which do not satisfy?
how to achieve it in sql server 2005?
TRN 259 3 9/9/2010 6622 68667(Rs) ABHIJIT KATARE
TRN 260 3 9/9/2010 6622 14635(Rs) ABHIJIT KATARE
TRN 235 3 9/9/2010 6586 68128 AJAY PARASRAMPURIA
TRN 236 3 9/9/2010 6586 14490 AJAY PARASRAMPURIA
TRN 257 3 9/9/2010 6621 68667 ANAND DESAI
TRN 258 3 9/9/2010 6621 14635 ANAND DESAI
TRN 287 3 9/9/2010 6817 119095 ANAND KATAKAM
TRN 242 3 9/9/2010 6594 95689 ANILKUMAR MUTHUNPARA
TRN 211 3 9/9/2010 6507 52239 ARBIND KUMAR GUPTA
TRN 212 3 9/9/2010 6538 63183 ASHOK KELKAR
TRN 185 3 9/9/2010 6431 140610 BANSAL Y.K
TRN 186 3 9/9/2010 6431 46845 BANSAL Y.K
TRN 248 3 9/9/2010 6600 72565 BENNO HANS LUKE
Try this for the select:
SELECT * FROM Table
GROUP BY CustomerName
HAVING SUM(LocalAmount) > 50000
Try this for delete (modified version of #RedFilter's):
delete from MyTable
where CustomerName in (
select CustomerName
from Table
group by CustomerName
having sum(LocalAmount) <= 50000
)
select * from MyTable group by CustomerName having sum(LocalAmount) > 50000
to see the good rows use:
SELECT
cusotmerName ,SUM(localAmount)
FROM YourTable
GROUP BY cusotmerName
HAVING SUM(localAmount)>50000
to delete the bad rows use:
DELETE YourTable
WHERE
CustomerName IN (SELECT
cusotmerName
FROM YourTable
GROUP BY cusotmerName
HAVING SUM(localAmount)<50000
)
This will show you the customers that have less than 50000:
select CustomerName, sum(LocalAmount)
from MyTable
group by CustomerName
having sum(LocalAmount) <= 50000
Note that you are better off grouping by CustomerID if there is one, as there could be duplicate names. Then, you can delete by doing this:
delete from MyTable
where CustomerID in (
select CustomerID
from MyTable
group by CustomerID
having sum(LocalAmount) <= 50000
)
this syntax looks a bit weird but it works!
;with cte as
(
select sum(LocalAmount) over (partition by cname) s
from yourtable
)
delete from cte where s <= 50000