I'm trying to find how many MED types have a child ORAL type that do NOT have a child IV type in the following table.
ID
PARENT_ID
TYPE
1
NULL
MED
2
1
ORAL
3
NULL
MED
4
3
ORAL
5
3
IV
6
NULL
MED
7
6
ORAL
8
NULL
MED
9
8
ORAL
12
NULL
MED
13
12
ORAL
14
12
IV
15
12
ORAL
I can find a count of All MED types that have a child ORAL type AND a child IV type with the following.
select count(distinct(a.ID))
from Table1 a
join Table1 b
on a.ID = b.PARENT_ID
join Table1 c
on a.ID = c.PARENT_ID
where a.TYPE = 'MED' and b.TYPE = 'ORAL' and c.TYPE = 'IV'
But I can't figure out how to filter out the MEDs that only have type ORAL and NOT type IV. This is what I tried but it returns nothing. It should return a count of 3 (rows 1, 6, 8).
select count(distinct(a.ID))
from Table1 a
join Table1 b
on a.ID = b.PARENT_ID
where a.TYPE = 'MED' and b.TYPE = 'ORAL'
and not exists (
select a.ID
from Table1 a
join Table1 b
on a.ID = b.PARENT_ID
join Table1 c
on a.ID = c.PARENT_ID
where a.TYPE = 'MED' and b.TYPE = 'ORAL' and c.TYPE = 'IV'
)
If I understand you correctly, then you can solve the problem like this
We take all records by condition and exclude keys where IV is present
SELECT COUNT(*)
FROM table1 t1
JOIN table1 t2
ON t1.id = t2.parent_id
AND t2.utype = 'ORAL'
WHERE t1.utype = 'MED'
AND t1.id NOT IN (SELECT parent_id FROM table1 t3 WHERE t3.utype = 'IV')
Table 1(5 records):
id
name
date
units
1
abc
3/16/2021
1
abc
3/17/2021
1
abc
3/18/2021
1
abc
3/19/2021
1
abc
3/20/2021
Table 2(3 records):
id
name
startdate
enddate
units
1
abc
3/16/2021
03/23/2021
2
1
abc
3/16/2021
03/23/2021
2
1
abc
3/16/2021
03/23/2021
2
Below is the join condition:
select * from Table1 a right join Table2 b on
(a.id = b.id) and (a.name = b.name) and (a.date between b.startdate and b.enddate)
I am trying to update the units columns in Table 1 from Table 2. My requirement is since there are 3 records in Table 2, only 3 records in Table 1 should be updated based on the above join condition. It can be random. But the number of records updated should not go above 3.
I tried doing this.
with e as
(select *,
row_number() over(partition by a.id
order by id) as rn
from Table1 a right join Table 2 b on (a.id = b.id) and (a.name = b.name) and (a.date between b.startdate and b.enddate)
)
update table1
set units = e.units
from e
where e.rn = 1
However, in this case all 5 records get updated. How do I resolve this? Any help is appreciated. Thank you.
Join the tables together. Then choose one row from from table2 for each row in table1 and do the update:
update table1 t1
set t1.units = t2.units
from (select distinct on (t1.id, t1.name, t1.date) t1.*, t2.units
from table1 t1 join
table2 t2
on t2.id = t1.id and t2.name = t1.name and
t1.date between t2.startdate and t2.enddate
order by t1.id, t1.name, t1.date, random())
) tt1
where tt1.name = t1.name and
tt1.id = t1.id and
tt1.date = t1.date;
I don't want to show my whole query as it is very specific but I will try to explain briefly.
The following query works perfectly and I got 6000 records as a result.
SELECT
DISTINCT ID,
NAME,
CASE WHEN A.ID IS NULL THEN 'NOT EX.'
ELSE A.Whatever
END AS A_Whatever,
D.Z1 AS A.P
--AND SO ON......
FROM A
INNER JOIN A ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
However, when i add a DATEDIFF calculation I get only 100 Rows in the answer:
SELECT DISTINCT
ID,
NAME,
CASE WHEN A.ID IS NULL THEN 'NOT EX.'
ELSE A.Whatever
END AS A_Whatever,
D.Z1 AS A.P,
DATEDIFF(dd,A.ADATE,A.BDATE)
FROM A
INNER JOIN A ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
I am expecting 6000 rows with a correct query using DATEDIFF in line with what the following query returns:
SELECT
DISTINCT *,
DATEDIFF(dd,A.ADATE,A.BDATE)
FROM A
INNER JOIN A ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
But I do not need all of them I need just the selected ones and the DATEDIFF but combining the queries above did not work for some reason that i do not know. Can anyone see why i am not getting the expected row count in my second query?
You can just wrap your query in a CTE and perform the DATEDIFF on the result set returned by the CTE:
WITH DISTINCT_CTE AS (
SELECT
DISTINCT ID,
NAME,
CASE WHEN A.ID IS NULL THEN 'NOT EX.'
ELSE A.Whatever
END AS A_Whatever,
D.Z1 AS A.P
--AND SO ON......
FROM A
INNER JOIN A ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
)
SELECT *, DATEDIFF(dd, ADATE, BDATE)
FROM DISTINCT_CTE
You could try a subquery... first subquery the entire thing.
In the receiving query do another subquery for the DATEDIFF. For this subquery you need the primary key to get back to the correct row for the dates, which if I'm interpreting correctly is A.ID.
SELECT dT.ID, dT.Name, dT.A_Whatever
,(SELECT DATEDIFF(dd, A2.ADATE, A2.BDATE)
FROM A AS A2
WHERE dT.ID = A2.ID --the primary key
) AS [DateDiff]
--AND SO ON........
FROM (
SELECT DISTINCT ID,
NAME,
CASE WHEN A.ID IS NULL THEN 'NOT EX.'
ELSE A.Whatever
END AS A_Whatever,
D.Z1 AS A.P
--AND SO ON......
FROM A
INNER JOIN A ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
) AS dT
You can try the following query :
SELECT T1.*, T2.DateDiff
FROM (
SELECT DISTINCT ID,
NAME,
CASE WHEN A.ID IS NULL THEN 'NOT EX.'
ELSE A.Whatever
END AS A_Whatever,
D.Z1 AS A.P
--AND SO ON......
FROM A
INNER JOIN B ON A.ID= B.ID AND A.Nb= B.Nb
LEFT JOIN T AS T2_ID ON T2_D.Z= A.Z
LEFT JOIN L1 ON A.NR = L1.NR AND A.S = L1.S
LEFT JOIN LF ON LF.NR = L1.LNR
--AND SO ON.......
) AS T1
JOIN (SELECT ID, DATEDIFF(dd, ADATE, BDATE) as DateDiff from A as A2) AS T2
ON T1.ID= T2.ID
As the following attempts to display, if you are using select distinct AND removing date columns from view when introducing datediff() into the select clause that could be the cause of the change in rows returned. Note in query 1 that as long as adate or bdate are displayed 5 rows would be returned, but without them (query 2) you just get one row. Alternatively, if you removed distinct,from query 2 you would get all 5 rows but just the one column (this isn't shown below).
try it out at SQL Fiddle
MS SQL Server 2014 Schema Setup:
CREATE TABLE Sample
([ADATE] datetime, [BDATE] datetime)
;
INSERT INTO Sample
([ADATE], [BDATE])
VALUES
('2017-10-01 00:00:00', '2017-10-06 00:00:00'),
('2017-10-02 00:00:00', '2017-10-07 00:00:00'),
('2017-10-03 00:00:00', '2017-10-08 00:00:00'),
('2017-10-04 00:00:00', '2017-10-09 00:00:00'),
('2017-10-05 00:00:00', '2017-10-10 00:00:00')
;
Query 1:
select distinct 'q1' qry, adate, bdate, datediff(day,adate,bdate) days_diff
from sample
order by adate
Results:
| qry | adate | bdate | days_diff |
|-----|----------------------|----------------------|-----------|
| q1 | 2017-10-01T00:00:00Z | 2017-10-06T00:00:00Z | 5 |
| q1 | 2017-10-02T00:00:00Z | 2017-10-07T00:00:00Z | 5 |
| q1 | 2017-10-03T00:00:00Z | 2017-10-08T00:00:00Z | 5 |
| q1 | 2017-10-04T00:00:00Z | 2017-10-09T00:00:00Z | 5 |
| q1 | 2017-10-05T00:00:00Z | 2017-10-10T00:00:00Z | 5 |
Query 2:
select distinct 'q2' qry, datediff(day,adate,bdate) days_diff
from sample
Results:
| qry | days_diff |
|-----|-----------|
| q2 | 5 |
I need short sql to left join T2 on T1 only if single math
T1 T2 Desired
F1 F2 F1 F2 F1 F2
1 A A RR 1
2 B A 2 UU
3 C A TT 3
4 D B UU 4 YY
5 E C VV 5 ZZ
C XX
D YY
E ZZ
You could use a simple GROUP BY/COUNT to count the rows per hit and a CASE expression to only output the value if the row count is <=1;
SELECT T1.F1, CASE WHEN COUNT(*)>1 THEN NULL ELSE MAX(T2.F2) END F2
FROM T1
LEFT JOIN T2 ON T1.F2 = T2.F1
GROUP BY T1.F1
An SQLfiddle to test with.
USING group by to eliminate the records with duplicates and doing left join to get all values from T1
select T1.F1, ISNULL(T2.F2,'') from T1
LEFT JOIN
(
select F1 from T2
group by F1
having count(*) =1
) T
on T1.F1 = T.F1
LEFT JOIN T2
on T2.F1 = T.F1
Select DISTINCT wpg.ID as id1,wr.ID as id2
FROM Table1 wpg
inner join Table2 wp ON wp.WpgId = wpg.ID
inner join Table3 wr ON wr.WpId = wp.ID
I need wpg.Id distinct how do this?
I need from:
1 2
2 3
1 4
get:
1 2
2 3
The answer depends on what you want to do with the second column. I'm assuming you want the smallest value:
select
wpg.ID as id1,
min(wr.ID) as id2
from
Table1 wpg
inner join Table2 wp on wp.WpgId = wpg.ID
inner join Table3 wr on wr.WpId = wp.ID
group by
wpg.ID
select wpg.ID, min(wr.ID)
FROM Table1 wpg
inner join Table2 wp ON wp.WpgId = wpg.ID
inner join Table3 wr ON wr.WpId = wp.ID
group by wpg.ID