How to query for non-matching records - sql

I would like to create a query that finds those members with no reviews.
Table 1 - items selected
member/audno
733 12
733 13
733 14
844 12
844 13
844 14
955 12
955 13
955 14
Table 2 - reviews
member/audno/reviewno
733 12 111
844 13 112
955 14 113
Create new query with results of members with items with no reviews:
member/audno
733 13
733 14
844 12
844 14
955 12
955 13
How can I do this?

Try this
SELECT *
FROM
items_selected I
WHERE
NOT EXISTS (
SELECT *
FROM
reviews R
WHERE
R.member = I.member AND R.audno = I.audno
)
Another, equivalent query is based on a left join
SELECT I.*
FROM
items_selected I
LEFT JOIN reviews R
ON I.member = R.member AND I.audno = R.audno
WHERE
R.member IS NULL
You might test both of them and look which one is more performant.

Related

Count number of unique occurrences of a key value corresponding to each ID column

I have a table in DB2 as below :
Key ID SubID
Abc123 576 10
Abc123 576 12
Abc124 576 13
Abc125 577 14
Abc126 578 15
Abc127 578 16
Abc128 578 17
Want to create a additional count column where it counts number of unique occurrences of key value for each ID and the output should be as below
Key ID SubID Count
Abc123 576 10 2
Abc123 576 12 2
Abc124 576 13 2
Abc125 577 14 1
Abc126 578 15 3
Abc127 578 16 3
Abc128 578 17 3
I tried below
select Key, ID, SubId ,
count(Key) over (partition by Key) as count
from table
Appreciate any help!
You cannot use a window function with the DISTINCT qualifier. You can use a scalar subquery to count the rows you want.
For example:
select *,
(select count(distinct key) from t x where x.id = t.id) as cnt
from t
Result:
KEY ID SUBID CNT
------- ---- ------ ---
Abc123 576 10 2
Abc123 576 12 2
Abc124 576 13 2
Abc125 577 14 1
Abc126 578 15 3
Abc127 578 16 3
Abc128 578 17 3
See running example at db<>fiddle.

Getting more data while converting data int to float and doing division and Multiplying with int?

I have three columns as shown in below tableA
Student Day Shifts
129 11 4
91 9 6
166 19 8
164 26 12
146 11 6
147 16 8
201 8 3
164 4 2
186 8 6
165 7 4
171 10 4
104 5 4
1834 134 67
I am writing a tvf to calculate Value of Points generated for Students as below
ALTER function Statagic(
#StartDate date
)
RETURNS TABLE
AS
RETURN
(
with src as
( select
Division=case when Shifts=0 then 0 else cast(Day as float)/cast(Shifts as float) end,*
from TableA
)
,tgt as
(select *,Points=Student*Division from src
)
select * from tgt)
When i execute above tvf(select * from Statagic('3/16/2014'))
My output is below
129 11 4 2.75 354.75
91 9 6 1.5 136.5
166 19 8 2.375 394.25
164 26 12 2.16666666666667 355.333333333333
146 11 6 1.83333333333333 267.666666666667
147 16 8 2 294
201 8 3 2.66666666666667 536
164 4 2 2 328
186 8 6 1.33333333333333 248
165 7 4 1.75 288.75
171 10 4 2.5 427.5
104 5 4 1.25 130
1834 134 67 2 3668
Note :
If you see the last row for three columns in the table is the total of rest column.So when you see the last row in the Output of TVF for last two columns when i am adding i am not getting same data i am getting more.
Guys please help me i am struggling to fix this bug i tried in all ways but i am unable to fix it.
select 354.75+136.5+394.25+355.333333333333+267.666666666667+294+536+328+248+288.75+427.5+130=3760.750000000000
3668 is not euql to 3760.75(I am getting more 100 value)

Microsoft access Query rolling total every 5 lines not using dates

I am new to Microsoft access.
I need a query that will allow me to sum a rolling total for every 5 lines of data. So on the sixth day I need a line to drop off the total and the new line to be added.
Fields:
ID, Daily_SUM
The results should be
ID Daily sum Weekly Sum
1 12
2 41
3 46
4 125
5 120 344
6 42 374
7 41 374
8 57 385
9 207 467
10 215 562
11 187 707
12 -43 623
13 45 611
14 56 460
15 40 285
16 8 106
17 95 244
18 580 779
19 360 1083
20 337 1380
You can do this with a correlated subquery. The challenge is actually getting NULL values on the first few rows:
select t.id, t.daily,
(select iif(count(*) = 7, sum(t3.daily), NULL)
from (select top 7 t2.daily
from table t2
where t2.id <= t.id
order by t2.id desc
) t3
) as weekly
from table t;
EDIT:
If we assume that the ids are assigned sequentially with no gaps, then you can use an explicit join:
select t.id, t.daily,
iif(count(*) = 7, sum(t2.daily), NULL) as weekly
from table t inner join
table t2
on t2.id between t.id - 6 and t.id
group by t.id, t.daily;

SQL Query: How to pull counts of two coulmns from respective tables

Given two tables:
1st Table Name: FACETS_Business_NPI_Provider
Buss_ID NPI Bussiness_Desc
11 222 Eleven 222
12 223 Twelve 223
13 224 Thirteen 224
14 225 Fourteen 225
11 226 Eleven 226
12 227 Tweleve 227
12 228 Tweleve 228
2nd Table : FACETS_PROVIDERs_Practitioners
NPI PRAC_NO PROV_NAME PRAC_NAME
222 943 P222 PR943
222 942 P222 PR942
223 931 P223 PR931
224 932 P224 PR932
224 933 P224 PR933
226 950 P226 PR950
227 951 P227 PR951
228 952 P228 PR952
228 953 P228 PR953
With below query I'm getting following results whereas it is expected to have the provider counts from table FACETS_Business_NPI_Provider (i.e. 3 instead of 4 for Buss_Id 12 and 2 instead of 3 for Buss_Id 11, etc).
SELECT BP.Buss_ID,
COUNT(BP.NPI) PROVIDER_COUNT,
COUNT(PP.PRAC_NO)PRACTITIONER_COUNT
FROM FACETS_Business_NPI_Provider BP
LEFT JOIN FACETS_PROVIDERs_Practitioners PP
ON PP.NOI=BP.NPI
group by BP.Buss_ID
Buss_ID PROVIDER_COUNT PRACTITIONER_COUNT
11 3 3
12 4 4
13 2 2
14 1 0
If I understood it correctly, you might want to add a DISTINCT clause to the columns.
Here is an SQL Fiddle, which we can probably use to discuss further.
http://sqlfiddle.com/#!2/d9a0e6/3

Exclude the specific kind of record

I am using SQL Server 2008 R2. I do have records as below in a table :
Id Sys Dia Type UniqueId
1 156 20 first 12345
2 157 20 first 12345
3 150 15 last 12345
4 160 17 Average 12345
5 150 15 additional 12345
6 157 35 last 891011
7 156 25 Average 891011
8 163 35 last 789521
9 145 25 Average 789521
10 156 20 first 963215
11 150 15 last 963215
12 160 17 Average 963215
13 156 20 first 456878
14 157 20 first 456878
15 150 15 last 456878
16 160 17 Average 456878
17 150 15 last 246977
18 160 17 Average 246977
19 150 15 additional 246977
Regarding this data, these records are kind of groups that have common UniqueId. The records can be of type "first, last, average and additional". Now, from these records I want to select "average" type of records only if they have "first" or "additional" kind of reading in group. Else I want to exclude them from selection..
The expected result is :
Id Sys Dia Type UniqueId
1 156 20 first 12345
2 157 20 first 12345
3 150 15 last 12345
4 160 17 Average 12345
5 150 15 additional 12345
6 157 35 last 891011
7 163 35 last 789521
8 156 20 first 963215
9 150 15 last 963215
10 160 17 Average 963215
11 156 20 first 456878
12 157 20 first 456878
13 150 15 last 456878
14 160 17 Average 456878
15 150 15 last 246977
16 160 17 Average 246977
17 150 15 additional 246977
In short, I don't want to select the record that have type="Average" and have only "last" type of record with same UniqueId. Any solution?
Using EXISTS operator along correlated sub-query:
SELECT * FROM dbo.Table1 t1
WHERE [Type] != 'Average'
OR EXISTS (SELECT * FROM Table1 t2
WHERE t1.UniqueId = t2.UniqueId
AND t1.[Type] = 'Average'
AND t2.[Type] IN ('first','additional'))
SQLFiddle DEMO
Try something like this:
SELECT * FROM MyTable WHERE [Type] <> 'Average'
UNION ALL
SELECT * FROM MyTable T WHERE [Type] = 'Average'
AND EXISTS (SELECT * FROM MyTable
WHERE [Type] IN ('first', 'additional')
AND UniqueId = T.UniqueId)
The first SELECT statement gets all records except the ones with Type = 'Average'. The second SELECT statement gets only the Type = 'Average' records that have at least one record with the same UniqueId, that is of type 'first' or 'additional'.