SQL : Get Column table twice with differents clause where - sql

I try to get the same column in the same table twice with different clauses :
My query:
SELECT
*
FROM
(SELECT TOP 10
CONVERT(DATE, attemptdate) AS Date,
Max(currentcount) AS A
FROM
logintracking
INNER JOIN
maxuser ON logintracking.loginid = maxuser.loginid
INNER JOIN
site ON site.siteid = maxuser.defsite
WHERE
attemptdate BETWEEN #dateDebut AND #dateFin
AND logintracking.clientaddr IN ('10.118.254.21', '10.118.254.156')
GROUP BY
CONVERT(DATE, attemptdate)
ORDER BY
CONVERT(DATE, attemptdate) ASC
) AS T1,
(SELECT TOP 10
CONVERT(DATE, attemptdate) AS Date,
MAX(currentcount) AS B
FROM
logintracking
INNER JOIN
maxuser ON logintracking.loginid = maxuser.loginid
INNER JOIN
site ON site.siteid = maxuser.defsite
WHERE
attemptdate BETWEEN #dateDebut AND #dateFin
AND logintracking.clientaddr = '10.118.254.35'
GROUP BY
CONVERT(DATE, attemptdate)
ORDER BY
CONVERT(DATE, attemptdate) ASC) AS T2
Result:
Desired result:
My objective is to get the same column 'max(currentcount)' twice and to apply different where clauses so to get two columns named (A & B), and i need also to show the date in the first column, can you please help ? Thanks

Since the only difference between A and B is logintracking.clientaddr, you can put that condition within a CASE statement within the MAX function:
SELECT CONVERT(DATE, attemptdate) AS Date,
MAX(CASE WHEN logintracking.clientaddr IN ( '10.118.254.21', '10.118.254.156' ) THEN currentcount END) AS A,
MAX(CASE WHEN logintracking.clientaddr IN ( '10.118.254.35' ) THEN currentcount END) AS B
FROM logintracking
INNER JOIN maxuser
ON logintracking.loginid = maxuser.loginid
INNER JOIN site
ON site.siteid = maxuser.defsite
WHERE attemptdate BETWEEN #dateDebut AND #dateFin
GROUP BY CONVERT(DATE, attemptdate)
ORDER BY CONVERT(DATE, attemptdate) ASC

Related

Join results of multiple select statements in sql

I have four select statements and I want to join them all to only get the common rows.
In an example, I'm providing 2 select statements:
SELECT
h.userid, 'Activity' as table_name,
h.stamp,
DATEDIFF(dd, kh.LatestDate, GETDATE()) as days_since,
m.group_name
FROM
([Animal].[SYSADM].[activity_history] h
INNER JOIN
(SELECT userid, MAX(stamp) as LatestDate
FROM [Animal].[SYSADM].[activity_history]
GROUP BY userid) kh ON h.userid = kh.userid AND h.stamp = kh.LatestDate)
LEFT OUTER JOIN
[Animal].[SYSADM].secure_member m ON m.user_name = h.userid
WHERE
(DATEDIFF(dd, kh.LatestDate, GETDATE()) > 90)
AND NOT (m.group_name = 'inactive')
ORDER BY
userid
SELECT
h.userid, 'Person' as table_name, h.stamp,
DATEDIFF(dd, kh.LatestDate, GETDATE()) as days_since,
m.group_name
FROM
([Animal].[SYSADM].[person_history] h
INNER JOIN
(SELECT userid, max(stamp) as LatestDate
FROM [Animal].[SYSADM].[person_history]
GROUP BY userid) kh ON h.userid = kh.userid AND h.stamp = kh.LatestDate)
LEFT OUTER JOIN
[Animal].[SYSADM].secure_member m ON m.user_name = h.userid
WHERE
(DATEDIFF(dd, kh.LatestDate, GETDATE()) > 90)
AND NOT (m.group_name = 'inactive')
ORDER BY
userid
I have tried INTERSECT, but it's not returning any rows, I want to see the common rows from both the select statements (actually I have 4 so I believe what works for 2 will work for 4)
Thanks in advance.
Update:
I tried inner join on 2 select statements and it gave me the desired result but now the question is how I can use inner join on 4 select statements.
SELECT DISTINCT t1.userid as A_UserID, t2.userid as P_UserID, t1.stamp as A_stamp, t2.stamp as P_stamp, datediff(dd,t1.stamp,GetDate()) as A_days_since, datediff(dd,t2.stamp,GetDate()) as P_days_since, t1.group_name, t1.table_name, t2.table_name
from
(SELECT h.userid, 'Activity' as table_name, h.stamp, datediff(dd,kh.LatestDate,GetDate()) as days_since, m.group_name
FROM
( [Animal].[SYSADM].[activity_history] h
inner join (
select userid, max(stamp) as LatestDate
from [Animal].[SYSADM].[activity_history]
group by userid
) kh on h.userid = kh.userid and h.stamp = kh.LatestDate
)
left outer join [Animal].[SYSADM].secure_member m on m.user_name = h.userid
where
(datediff(dd,kh.LatestDate, GetDate()) > 90)
and not (m.group_name = 'inactive')) t1
inner join
(SELECT h.userid, 'Person' as table_name, h.stamp, datediff(dd,kh.LatestDate,GetDate()) as days_since, m.group_name
FROM
( [Animal].[SYSADM].[person_history] h
inner join (
select userid, max(stamp) as LatestDate
from [Animal].[SYSADM].[person_history]
group by userid
) kh on h.userid = kh.userid and h.stamp = kh.LatestDate
)
left outer join [Animal].[SYSADM].secure_member m on m.user_name = h.userid
where
(datediff(dd,kh.LatestDate, GetDate()) > 90)
and not (m.group_name = 'inactive')) t2
on
t1.userid = t2.userid
order by T1.userid
Query Result
Forget about the UNION for a moment. Imagine you take that result and insert into Table1
Then depend what you mean the "common rows". If you want exact value but in different tables
SELECT userid, h.stamp, days_since, m.group_name
FROM Table1
GROUP BY userid, h.stamp, days_since, m.group_name
HAVING COUNT( table_name ) = 2 -- in this case 2 because are two types
-- Activity and Persons
After viewing your query result you also need to add DISTINCT to each of the queries on the UNION.

SQL Oracle/Joining two queries

I have two queries which I need to stitch together but I’m not sure how….
This first query pulls through the last three reconciled amounts for any chosen account from a table of accounts, reconciled amounts, periods, and any amount written off (if there was any)
SELECT *
FROM (
SELECT *
FROM (
SELECT gwod.account_id,
EXTRACT(month FROM gwod.charge_period_start) charge_period_month,
SUM(gwod.total_due_on_charge) total_due_on_charge,
SUM(gwod.amount_written_off) amount_written_off,
DENSE_RANK() over (PARTITION BY gwod.account_id
ORDER BY EXTRACT(month FROM
gwod.charge_period_start) DESC) rownumber
FROM Accounts_report gwod
WHERE account_id IN ('')
GROUP BY gwod.account_id,
EXTRACT(month FROM gwod.charge_period_start)
HAVING SUM (gwod.total_due_on_charge) <> 0) t1
WHERE t1.rownumber <=3)
PIVOT (MAX(charge_period_month) charge_period,
MAX(total_due_on_charge) total_due_on_charge,
MAX(amount_written_off) amount_written_off
FOR rownumber IN (1,2,3))
ORDER BY account_id
This query essentially gets me the list of accounts which I’m interested in from some additional tables...
WITH Account_Owners AS
(select gs.account_id, AP.SUPERVISOR
from Account_Info gs
Left join ACC_OWNERS AD
On gs.account_id = AD.ACCOUNT_NUMBER
Left Join Onwers_Info AP
On ad.owned_by = AP.ADNAME
group by account_id, AP.SUPERVISOR
)
SELECT distinct POLICY_INFO.ACCOUNT_ID, Count (POLICY_INFO.POLICY_NO) As
Active, a.supervisor
FROM POLICY_INFO
inner join Account_owners a on policy_info.account_id = a.account_id
WHERE Policy_Info.POLICY_STATUS = 'Active'
And policy_info.ACCOUNT_ID is not Null
And a.supervisor in ('David Smith')
GROUP BY Policy_Info.ACCOUNT_ID, a.supervisor
ORDER BY Policy_Info.ACCOUNT_ID
What I want to do is have the one query which pulls through the last three reconciled amounts (as per the first query) for all of the accounts of interest (as per the second query); I’m having trouble combining the two however into the single query however…
Add the first query as another set in the with clause and INNER JOIN it.Also DISTINCT might not be required in the final select as you are grouping any way. Try this and let me know if it's correct as it is very difficult for me to visualize data only with the query.
WITH Account_charges AS
(
SELECT *
FROM (
SELECT *
FROM (
SELECT gwod.account_id,
EXTRACT(month FROM gwod.charge_period_start) charge_period_month,
SUM(gwod.total_due_on_charge) total_due_on_charge,
SUM(gwod.amount_written_off) amount_written_off,
DENSE_RANK() over (PARTITION BY gwod.account_id
ORDER BY EXTRACT(month FROM gwod.charge_period_start) DESC) rownumber
FROM Accounts_report gwod
WHERE account_id IN ('')
GROUP BY gwod.account_id,
EXTRACT(month FROM gwod.charge_period_start)
HAVING SUM (gwod.total_due_on_charge) <> 0) t1
WHERE t1.rownumber <=3)
PIVOT (MAX(charge_period_month) charge_period,
MAX(total_due_on_charge) total_due_on_charge,
MAX(amount_written_off) amount_written_off
FOR rownumber IN (1,2,3))
),
Account_Owners AS
(select gs.account_id, AP.SUPERVISOR
from Account_Info gs
Left join ACC_OWNERS AD
On gs.account_id = AD.ACCOUNT_NUMBER
Left Join Onwers_Info AP
On ad.owned_by = AP.ADNAME
group by account_id, AP.SUPERVISOR
)
SELECT distinct POLICY_INFO.ACCOUNT_ID, Count (POLICY_INFO.POLICY_NO) As
Active, a.supervisor ,MAX(b.charge_period),MAX(b.total_due_on_charge),MAX(b.amount_written_off)
--use the proper column names.
FROM POLICY_INFO
inner join Account_owners a on policy_info.account_id = a.account_id
INNER JOIN Account_charges b ON policy_info.account_id = b.account_id
Where Policy_Info.POLICY_STATUS = 'Active'
And policy_info.ACCOUNT_ID is not Null
And a.supervisor in ('David Smith')
Group by Policy_Info.ACCOUNT_ID, a.supervisor
order by Policy_Info.ACCOUNT_ID;

SQL server show count 0 when no record is found

I'm trying to make this query show 0 in the "nb" field when there are no record found for a specific date. Right now the output is 0 row, unless the date i specify exists in the "Commande" table.
SELECT
isnull(COUNT(*), 0) as nb,
CONVERT(date, c.Date_commande) as Date_commande,
f.Code_fournis
FROM Commande c
LEFT JOIN Fournisseur f
ON c.Code_fournis = f.Code_fournis
WHERE f.Code_fournis = 'XNZ'
AND Convert(date, c.Date_commande) = '2015-10-28'
GROUP BY CONVERT(date, c.Date_commande), f.Code_fournis
ORDER BY c.date_commande desc
The problem is you can't count what isn't there. You need create a table allDates for all the dates. 100 years mean 36,500 rows so is a small table. Use this one as example
How can I generate a temporary table filled with dates in SQL Server 2000?
Then
SELECT
isnull(COUNT(*), 0) as nb,
CONVERT(date, AD.date) as Date_commande,
f.Code_fournis
FROM
allDates AD
LEFT JOIN Commande c
ON AD.date = CONVERT(date, c.Date_commande)
LEFT JOIN Fournisseur f
ON c.Code_fournis = f.Code_fournis
WHERE f.Code_fournis = 'XNZ'
AND Convert(date, c.Date_commande) = '2015-10-28'
GROUP BY CONVERT(date, AD.date), f.Code_fournis
ORDER BY AD.date desc
Because '2015-10-28' does not exists in Commande, you need to create an row for it in a dummy table:
SELECT
SUM(case when c.Date_commande is null then 0 else 1 end) as nb,
d.Date_commande as Date_commande,
f.Code_fournis
FROM (values(cast('20150101' as date), 'XNZ') as d(Date_commande, Code_fournis)
LEFT JOIN Commande c on Cast(c.Date_commande as date) = d.Date_commande
LEFT JOIN Fournisseur f
ON c.Code_fournis = f.Code_fournis and f.Code_fournis = d.Code_fournis
GROUP BY d.Date_commande, f.Code_fournis
ORDER BY d.Date_commande desc
This would work as well:
SELECT isnull(COUNT(*), 0) as nb,
CONVERT(date, c.Date_commande) as Date_commande,
f.Code_fournis
From your query
Union All
Select 0, '20150101', 'XNZ'
Where not exist (
select 1
From Commande c
LEFT JOIN Fournisseur f
ON c.Code_fournis = f.Code_fournis and = d.Code_fournis
Where f.Code_fournis = 'XNZ'
AND Convert(date, c.Date_commande) = '20150101'
)
Even though this is old and has a few downvotes, I recently solved my problem. I had to generate a table with dates.
SELECT SUM(CONVERT(int, case(vtl.oeil) WHEN RTRIM('I') THEN 2 ELSE 1 END)) as nb,
CONVERT(date, c.Date_commande) as Date_commande,
RTRIM(f.Code_fournis) AS Code_fournis
FROM Commande c
LEFT JOIN Fournisseur f
ON c.Code_fournis = f.Code_fournis
WHERE c.Code_fournis = 'XNZ'
AND Convert(date, c.Date_commande)
BETWEEN '2015-11-30'
AND '2015-12-04'
GROUP BY CONVERT(date, c.Date_commande), f.Code_fournis
UNION ALL
SELECT '0', date, 'XNZ'
FROM allDates
WHERE date
BETWEEN '2015-11-30'
AND '2015-12-04'
AND date NOT IN (
SELECT convert(date, c.Date_commande) as date
FROM allDates ad
INNER JOIN Commande c
ON ad.date = convert(date, c.Date_commande)
WHERE c.Code_fournis = 'XNZ'
and convert(date, c.Date_commande)
BETWEEN '2015-11-30'
AND '2015-12-04'
)
ORDER BY c.date_commande asc
It's a bit different then what I asked for but hopefully it can help someone.

Select the highest Id Where serviceId occurs more than once

I have inherited a codebase in Web forms and are having trouble with a SQL query.
SELECT foretag.namn, foretag.epost, foretag.forlangEj, service_fakturering.*
FROM foretag
INNER JOIN service ON foretag.id = service.foretagsid
INNER JOIN service_fakturering ON service.id = service_fakturering.service_id
WHERE service_fakturering.giltighets_datum <= DATEADD(D, 30, GETDATE())
ORDER BY bestallnings_datum DESC, id DESC
In the table service_fakturering there are multiple rows with the same service_id
I need to select the last one, max id, to be used in the INNER JOIN service_fakturering ON service.id = service_fakturering.service_id
Using ROW_NUMBER() function, along with common table expression, it can be done like this:
WITH cte_service_fakturering AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY service_id ORDER BY id DESC) RN
FROM service_fakturering
)
SELECT foretag.namn, foretag.epost, foretag.forlangEj, cte.*
FROM foretag
INNER JOIN service ON foretag.id = service.foretagsid
INNER JOIN cte_service_fakturering cte ON service.id = cte.service_id AND cte.RN = 1
WHERE service_fakturering.giltighets_datum <= DATEADD(D, 30, GETDATE())
ORDER BY bestallnings_datum DESC, id DESC
The Sub select will group your service_fakturering rows and get the maxId for you. This is then used to join back into your query and filter for only those rows you are interested in.
SELECT foretag.namn, foretag.epost, foretag.forlangEj, service_fakturering.*
FROM foretag
INNER JOIN service ON foretag.id = service.foretagsid
INNER JOIN service_fakturering ON service.id = service_fakturering.service_id
INNER JOIN (Select service_fakturering.service_id, Max(service_fakturering.id) as Id
FROM service_fakturering
GROUP BY service_fakturering.service_id) x
ON x.service_id = service_fakturering.service_id
AND x.Id = service_fakturering.Id
WHERE service_fakturering.giltighets_datum <= DATEADD(D, 30, GETDATE())
ORDER BY bestallnings_datum DESC, id DESC
Try this...
You could use ROW_NUMBER to denote an order for the set
WITH CTE
AS (
SELECT *
, ROW_NUMBER() OVER (
PARTITION BY service_id ORDER BY ID DESC
) ROWNUM
FROM service_fakturering
)
SELECT foretag.namn
, foretag.epost
, foretag.forlangEj
, service_fakturering.*
FROM foretag
INNER JOIN service
ON foretag.id = service.foretagsid
INNER JOIN service_fakturering
ON service.id = service_fakturering.service_id
AND ROW_NUM = 1
WHERE service_fakturering.giltighets_datum <= DATEADD(D, 30, GETDATE())
ORDER BY bestallnings_datum DESC
, id DESC

Obtaining only first result from a LEFT JOIN

I'm trying to get the first result of a LEFT JOIN for each row of a SELECT statement.
Because now right now, if I have 100 rows in the joined table, I'll get 100 times the same row from the SELECT. I'd just need the first joined row so that way I wouldn't get any duplicates.
I can't use GROUP BY because I have to get more than only one row from the table.
Here's a basic version of my query:
SELECT bg.PatientID, DATEDIFF(hour, bg.CreateDate, GETDATE()) TimeToTarget
FROM BloodGlucose bg
LEFT JOIN IVProtocol i ON i.PatientID = bg.PatientID
WHERE bg.BGValue >= i.TargetLow AND bg.BGValue <= i.TargetHigh
ORDER BY bg.PatientID ASC
I tried using DISTINCT but since the data from bg.CreateDate isn't always the same it returns duplicates.
I just need the FIRST row of that left joined table.
Any ideas/suggestions?
Thanks!
;WITH x AS
(
SELECT
bg.PatientID,
TimeToTarget = DATEDIFF(hour, bg.CreateDate, GETDATE()),
rn = ROW_NUMBER() OVER (PARTITION BY bg.PatientID ORDER BY bg.CreatedDate DESC)
FROM dbo.BloodGlucose AS bg
LEFT JOIN dbo.IVProtocol AS i
ON i.PatientID = bg.PatientID
WHERE bg.BGValue >= i.TargetLow
AND bg.BGValue <= i.TargetHigh
)
SELECT PatientID, TimeToTarget
FROM x
WHERE rn = 1
ORDER BY PatientID;
To join to other results:
;WITH x AS
(
... same as above ...
)
SELECT x.PatientID, x.TimeToTarget, y.Something
FROM x INNER JOIN dbo.SomethingElse AS y
ON x.PatientID = y.PatientID
WHERE x.rn = 1
ORDER BY x.PatientID;
SELECT bg.PatientID, DATEDIFF(hour, bg.CreateDate, GETDATE()) TimeToTarget
FROM BloodGlucose bg
cross apply (
select top 1 *
from IVProtocol i
where i.PatientID = bg.PatientID
order by SOME_CRITERA
) i
WHERE bg.BGValue >= i.TargetLow AND bg.BGValue <= i.TargetHigh
ORDER BY bg.PatientID ASC
Cross apply is a handy tool for such situations. It works like a join but you can use variables inside the subquery.