Display values that are out of scope in addition to in scope - sql

So I have a complex situation.
I have a 3 tables:
Product
Resource Name
Resource Type
C1
Bold
E2
Crema
C2
Bold
C3
Bold
Purchase_History
Resource Name
Qty
Cust ID
Date
Batch
C1
7
123
Jun 1
324
C1
7
222
Jun 10
324
C1
7
333
Jun 11
4BZ
C1
7
124
Jun 11
4BZ
C1
7
125
Jun 11
324
C1
7
111
Jun 21
324
C2
7
55
Jun 22
A22
C2
7
1
Jun 24
A22
Inventory
Resource Name
Available
Qty
Batch
C1
1
40
324
C2
1
50
3GC
C1
2
0
4BZ
C2
1
99
A22
E2
1
99
B22
E2
2
0
C22
So I've created a query as below:
Select
p.resourcename
, ph.cust_id
, ph.batch
, case when i.available=1 then 'Yes' when i.available=2 then 'no' else ''end 'In Stock'
from product p
join purchase_history ph on ph.resource_name=p.resource_name
join inventory i on i.batch=ph.batch
where
ph.date >='Jun 1'
ph.date <='Jun 20'
I am getting the following:
Resource Name
Cust Id
Batch
In Stock
C1
123
324
Yes
C1
222
324
Yes
C1
333
4BZ
No
C1
124
4BZ
No
C1
123
324
Yes
What I would like to achieve is the below, where even though the last 2 batch and products are out of the range of transactions, we can still see them as below. I know this is a weird as but essentially the team wants to see what has been sold so far - within the date range - and all product availability status. Is this something achievable?
Resource Name
Cust Id
Batch
In Stock
C1
123
324
Yes
C1
222
324
Yes
C1
333
4BZ
No
C1
124
4BZ
No
C1
123
324
Yes
C2
n/a
3GC
Yes
C2
n/a
A22
Yes
E2
n/a
B22
Yes
E2
n/a
C22
No

you need to use left join with purchase_history table:
Select
p.resourcename
, ph.cust_id
, i.batch
, case when i.available=1 then 'Yes' when i.available=2 then 'no' else ''end 'In Stock'
from product p
join inventory i on i.resource_name=p.resource_name
left join purchase_history ph
on ph.resource_name=p.resource_name
and i.batch=ph.batch
where
ph.date >='Jun 1' and ph.date <='Jun 20'
notice I changes the order of tables for better readability.

Related

Exclude rows where keys match, but are on different rows

I'm looking for the best way to produce the result set in the scenario provided. My cust3 column isn't identifying the repeated values in the indvid2 column. The end result I'm looking for is to exclude the rows where key1 and key2 match (ids:1,2,6 and 7), then sum accounts where the acctids match.If there's a better way to code this, I welcome all suggestions. Thanks!
WITH T10 as (
SELECT acctid,invid,(
case
when invid like '%-R' then left (InvID,LEN(invid) -2) else InvID
END) as InvID2
FROM table x
GROUP BY acctID,invID
),
T11 as (
SELECT acctid, Invid2, COUNT(InvID2) as cust3
FROM T10
GROUP BY InvID2,acctid
HAVING
COUNT (InvID2) > 1
)
select DISTINCT
a.acctid,
a.name,
b.invid,
C.invid2,
D.cust3,
b.amt,
b.key1,
b.key2
from table a
inner join table b (nolock) on a.acctid = b.acctid
inner join T10 C (nolock) on b.invid = c.invid
inner join T11 D (nolock) on C.invid2 = D.invid2
Resultset
id acctID name invid invid2 Cust3 amt key1 key2
1 123 James 101 101 2 $500 NULL 6789
2 123 james 101-R 101 2 ($500) 6789 NULL
3 123 James 102 102 2 $350 NULL NULL
4 123 James 103 103 2 $200 NULL NULL
5 246 Tony 98-R 98 2 ($750) 7423 NULL
6 432 David 45 45 2 $100 NULL 9634
7 432 David 45-R 45 2 ($100) 9634 NULL
8 359 Stan 39-R 39 2 ($50) 6157 NULL
9 753 George 95 95 2 $365 NULL NULL
10 753 George 108 108 2 $100 NULL NULL
Desired Resultset
id acctID name invid invid2 Cust3 amt key1 key2
1 123 James 101 101 2 $500 NULL 6789
2 123 james 101-R 101 2 ($500) 6789 NULL
3 123 James 102 102 1 $350 NULL NULL
4 123 James 103 103 1 $200 NULL NULL
5 246 Tony 98-R 98 1 ($750) 7423 NULL
6 432 David 45 45 2 $100 NULL 9634
7 432 David 45-R 45 2 ($100) 9634 NULL
8 359 Stan 39-R 39 1 ($50) 6157 NULL
9 753 George 95 95 1 $365 NULL NULL
10 753 George 108 108 1 $100 NULL NULL
Then to sum amt by acctid
id acctid name amt
1 123 James $550
2 246 Tony ($750)
3 359 Stan ($50)
4 753 George $465
Something like:
;WITH Keys as (
SELECT Key1.acctID, [Key] = Key1.Key1
FROM YourTable as Key1
INNER JOIN YourTable as Key2
ON Key1.Key1 = Key2.Key2 and Key1.acctID = Key2.acctID
)
SELECT t.acctID, t.name, amt = SUM(t.amt)
FROM YourTable as t
LEFT JOIN Keys as k
ON t.acctID = k.acctID and (t.Key1 = [Key] or t.Key2 = [Key])
WHERE k.acctID is Null
GROUP BY t.acctID, t.name

SQL Multiple foreign keys referring to the same table

I have the following table Student:
Id FirstName LastName State Index Year Course1 Course2 Course3 Course4 Course5
622 Student622 LastName622 State17 62200 2 54 47 68 67 50
623 Student623 LastName623 State16 62300 3 17 99 37 99 32
624 Student624 LastName624 State2 62400 4 8 71 11 58 86
625 Student625 LastName625 State1 62500 2 39 75 33 77 17
626 Student626 LastName626 State15 62600 3 11 3 4 70 72
627 Student627 LastName627 State13 62700 2 84 77 65 62 76
628 Student628 LastName628 State13 62800 4 87 18 19 4 75
629 Student629 LastName629 State10 62900 2 96 67 14 97 31
The numbers in Course 1, 2, 3, 4, 5 are foreign key values that refer to the id of the following Courses table:
Id Name ProfessorId
1 Course 1 8
2 Course 2 14
3 Course 3 4
4 Course 4 3
5 Course 5 6
6 Course 6 2
7 Course 7 14
8 Course 8 4
9 Course 9 5
How can write script so that when i execute instead of foreign key numbers there is the Course name? Any thoughts?
You could LEFT JOIN to the Course table for each course id.
SELECT
s.Id, s.FirstName, s.LastName, s.State, s.[Index], s.[Year],
c1.Name as Course1Name,
c2.Name as Course2Name,
c3.Name as Course3Name,
c4.Name as Course4Name,
c5.Name as Course5Name
FROM Student s
LEFT JOIN Courses c1 ON c1.Id = s.Course1
LEFT JOIN Courses c2 ON c2.Id = s.Course2
LEFT JOIN Courses c3 ON c3.Id = s.Course3
LEFT JOIN Courses c4 ON c4.Id = s.Course4
LEFT JOIN Courses c5 ON c5.Id = s.Course5
Because those are all LEFT JOIN's, all the records of Student will be returned.
Even if some course id's aren't filled in.

How to display on a certain amount of data for a specific column

Consider the following table
Dept product name parts WO
32 aa abc 11 1234
32 aa aas 18 2213
32 bb asd 16 3424
32 aa adf 19 1255
32 cc asa 10 7567
32 aa agd 11 1233
31 ss fsf 23 3434
I have around 100 dept. in my table. What I want is that when the dept. is 32 and the product is "aa", I only want to display 30 parts or less. So in this case the total number of parts for aa is 59. So the first aa product has 11 parts and the next aa product has 18 parts so that's 29. It should now ignore all the other aa products.
Expected Output
Dept product name parts WO
32 aa abc 11 1234
32 aa aas 18 2213
32 bb asd 16 3424
32 cc asa 10 7567
31 ss fsf 23 3434
Appreciate any help provided.
Assuming WO is a primary key then use SUM window function to solve it.
SELECT yt.Dept, yt.product, yt.name, yt.parts, yt.WO
FROM yourtable yt
LEFT JOIN (
SELECT *, sum(y.parts) over (partition by y.dept order by y.parts) tsum
FROM yourtable y
WHERE y.product = 'aa'
) t ON yt.WO= t.WO
WHERE yt.dept != 32 or (yt.dept = 32 and t.tsum < 59) or (yt.dept = 32 and yt.product != 'aa')
you can use SUM() window function where you have to partition by dept and product
SELECT dept,
product,
name,
parts,
wo
FROM (SELECT *,
SUM(parts) OVER (PARTITION BY dept, product ORDER BY name) rt
FROM t
) t_rt
WHERE rt <= 30
ORDER BY dept DESC,
product,
wo
Result
dept product name parts wo
32 aa abc 11 1234
32 aa aas 18 2213
32 bb asd 16 3424
32 cc asa 10 7567
31 ss fsf 23 3434

Why is T-SQL Returning Duplicate Rows, Join Issue I Believe

The code as written below returns the appropriate customers, lockers, units and balance. However, when I add in the commented-out code it reiterates each customer's data for each club even though each customer can only be a member of one club.
USE db1
GO
SELECT [db1].[dbo].[Customer].[CustomerNumber] AS 'Customer No.'
-- ,A. ClubID AS 'Club ID No.'
,(SELECT CONCAT (SI.Locker, '-', SI.Frequency)) AS Locker
,SI.Unit AS Unit
--,[db2].[dbo].[vueClub].Club_aka AS Club
,[db1].[dbo].[Customer_Balance].[CurrentBalance]
FROM [db1].[dbo].[Customer_Balance]
JOIN [db1].[dbo].[Customer]
ON [db1].[dbo].[Customer_Balance].POSCusNo = Customer.CustomerNumber
JOIN [SQLSrv01].[ db3].[dbo].[md_Table_1] AS D
ON D.Contract_no = [db1].[dbo].[Customer_Balance]. POSCusNo
JOIN [SQLSrv01].[ db2].[dbo].[vueSoldLockers] AS SI
ON SI.CustomerID = [db1].[dbo].[Customer].CustomerID
--JOIN [db2].[dbo].[vueClub] AS A
--ON [db1].[dbo].[Customer].SiteID = A.SiteID
WHERE [db1].[dbo].[Customer_Balance].StatusCode = '1234'
ORDER BY Customer.CustomerNumber ASC
So if I run it as is I get:
Customer No. Locker Unit Current Balance
1 315 A1 456.00
2 316 A3 1204.70
3 317 B2 335.60
4 318 B4 1500.30
But if I include the commented-out code I get:
Customer No. Club ID No Locker Unit Club Current Balance
1 4 315 A1 Tigers 456.00
1 3 315 A1 Lions 456.00
2 4 316 A3 Tigers 1204.70
2 3 316 A3 Lions 1204.70
3 4 317 B2 Tigers 335.60
3 3 317 B2 Lions 335.60
4 4 318 B4 Tigers 1500.30
4 3 318 B4 Lions 1500.30
Is it because I don't have the JOIN set up properly?
Customer No. Club ID No Locker Unit Club Current Balance
1 4 315 A1 Tigers 456.00
1 3 315 A1 Lions 456.00
You are joining customer to vueClub on SiteID. Looks like the site customer 1 is in, has 2 clubs (3, 4)

Tsql compare two field in the result set

I have two tables : table_A and table_W. I want to get only the non-matching payment details with the corresponding descriptions. The table are:
table_W
adharno phone descrip_w amount_w
1 11 p1 100
2 22 p1 250
2 22 p2 250
2 22 p3 300
2 33 p1 150
2 33 p2 150
2 33 p3 400
3 55 p1 50
3 66 p1 100
table_A
adharno phone decrip_a amount_a
1 11 p1 110
2 22 p1 150
2 22 p2 150
2 22 p3 400
2 33 p1 250
2 33 p2 250
2 33 p3 300
3 55 p1 100
3 66 p1 50
I am getting the following result.
adharno phone descrip_w amount_w decrip_a amount_a
1 11 p1 100 p1 110
2 22 p1 250 p1 150
2 22 p2 250 p2 150
2 22 p3 300 p3 400
2 33 p1 150 p1 250
2 33 p2 150 p2 250
2 33 p3 400 p3 300
3 55 p1 50 p1 100
3 66 p1 100 p1 50
But the result I am looking is as follows
adharno phone descrip_w amount_w decrip_a amount_a
1 11 p1 100 p1 110
I want to compare the matching descrip, even if the phoneno is different but the adhaarno should be same.
How about:
SELECT w.adharno,
w.phone w_phone,
descrip_w,
amount_w,
a.phone a_phone,
decrip_a,
amount_a
FROM table_w w
JOIN table_a a ON a.adharno = w.adharno
AND w.descrip_w = a.decrip_a
AND (w.phone <> a.phone
OR w.amount_w <> a.amount_a)