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

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)

Related

looking for values from another table where they do not exist in a given group

I have two tables:
SHOPPING
date
id_customer
id_shop
id_fruit
28.03.2018
7423
123
1
13.02.2019
8408
354
1
28.03.2019
7767
123
9
13.02.2020
8543
472
7
28.03.2020
8640
346
9
13.02.2021
7375
323
9
28.03.2021
7474
323
8
13.02.2022
7476
499
1
28.03.2022
7299
123
4
13.02.2023
8879
281
2
28.03.2023
8353
452
1
13.02.2024
8608
499
6
28.03.2024
8867
318
1
13.02.2025
7997
499
6
28.03.2025
7715
499
4
13.02.2026
7673
441
7
FRUITS
id_fruit
name
1
apple
2
pear
3
grape
4
banana
5
plum
6
melon
7
watermelon
8
orange
9
pineapple
I would like to find fruits that have never been bought in a specific id_shop
I tried with this:
SELECT
s.idshop,
s.id_fruit ,
f.name
FROM
shopping s
LEFT JOIN fruit f ON f.id_fruit = s.id_fruit
WHERE NOT EXISTS (
SELECT *
FROM
fruit f1
WHERE f1.id_fruit = s.id_fruit
)
but it does not work...
Yes, you need an OUTER JOIN, but that should be RIGHT JOIN along with NULL values picked from shopping table after join applied, considering your current query such as
SELECT f.*
FROM shopping s
RIGHT JOIN fruit f
ON f.id_fruit = s.id_fruit
WHERE s.id_fruit IS NULL
Demo

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

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.

Select sum shown null value in left join SQL statement

I have three tables and expecting the result as below but i do not know how to correct my sql statement.
select history.company,history.ghacct,rpt_revenue.revenue,rpt_revenue.other, isnull(guest.stay,0) as stay, isnull(guest.nights,0) as nights
from history
left join(select company,count(*) as stay,sum(nights) as nights from guest group by company) guest on guest.company=history.company
left join (select ghacct,sum(revenue) as revenue, sum(other) as other
from rpt_revenue group by ghacct) rpt_revenue on rpt_revenue.ghacct=history.ghacct
where history.type='c' group by history.company, history.ghacct,rpt_revenue.revenue, rpt_revenue.other,guest.stay,guest.nights order by history.company asc;
history
ghacct company type
33 JOINT LTD 10010205687 c
3B GLOBAL 10010350619 c
3E FASHION 10010244145 c
3P INT'L 10010112089 c
guest
company stay nights
33 JOINT LTD 01/01/2009 1
33 JOINT LTD 01/06/2009 1
3B GLOBAL 10/02/2019 2
3E FASHION 09/25/2008 6
3P INT'L 08/26/2009 3
3P INT'L 04/26/2010 9
rpt_revenue
ghacct revenue other
10010205687 20 10
10010205687 10 10
10010350619 30 2
10010244145 15 3
10010112089 16 8
10010112089 4 2
Result
company ghacct revenue other stay nights
33 JOINT LTD 10010205687 NULL NULL 2 2
3B GLOBAL 10010350619 NULL NULL 1 2
3E FASHION 10010244145 NULL NULL 1 6
3P INT'L 10010112089 NULL NULL 2 12
Expected result
company ghacct revenue other stay nights
33 JOINT LTD 10010205687 30 20 2 2
3B GLOBAL 10010350619 30 2 1 2
3E FASHION 10010244145 15 3 1 6
3P INT'L 10010112089 20 10 2 12
I think the main problem with your current query lies in the GROUP BY clause, which should really only be aggregating by company and account. In addition, you might want to use ISNULL for the revenue and other amount, as you are already doing so for stay and nights.
SELECT
h.company,
h.ghacct,
ISNULL(rr.revenue, 0) AS revenue,
ISNULL(rr.other, 0) AS other,
ISNULL(g.stay, 0) AS stay,
ISNULL(g.nights, 0) AS nights
FROM history h
LEFT JOIN
(
SELECT company, COUNT(*) AS stay, SUM(nights) AS nights
FROM guest
GROUP BY company
) g
ON g.company = h.company
LEFT JOIN
(
SELECT ghacct, SUM(revenue) AS revenue, SUM(other) AS other
FROM rpt_revenue
GROUP BY ghacct
) rr
ON rr.ghacct = h.ghacct
WHERE
h.type = 'c'
GROUP BY
h.company,
h.ghacct
ORDER BY
h.company;

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

How to join different table some column?

Student Table 1
ID Name Surname School Number Class Number ClassBranch
-----------------------------------------------------------------------------
113 Jane Smith 19 4 A
121 John Konl 42 5 B
331 Albert Smith 61 4 A
742 Jack Ronal 52 5 B
759 Jan Ronal 84 6 C
Student Table 2
ID Name Surname School Number Class Number Class Branch
-----------------------------------------------------------------------------
113 Jane Smith 11 4 D
151 John Konl 18 4 D
804 Albert Smith 26 5 F
605 Jack Ronal 32 5 F
785 Jan Ronal 87 8 L
Created Student Table
ID Name Surname School Number Class Number Class Branch
--------------------------------------------------------------------
113 Jane Smith NULL NULL NULL
151 John Konl NULL NULL NULL
804 Albert Smith NULL NULL NULL
605 Jack Ronal NULL NULL NULL
NULL NULL NULL 11 4 D
NULL NULL NULL 18 4 D
NULL NULL NULL 26 5 F
NULL NULL NULL 32 5 F
I want this table
ID Name Surname School Number Class Number Class Branch
113 Jane Smith 11 4 D
151 John Konl 18 4 D
804 Albert Smith 26 5 F
605 Jack Ronal 32 5 F
I want to Student Table 1 ---> ID,Name,Surname and Student Table 2 --> School Number,Class Number and ClassBranch joın.But joın is not successful.Class Branch A and B removed and D,F is adding.
First table ID,Name,Surname (3 columns) and Second table School Number,Class Number,Class Branch join.
Where conditions:
Removed column --> 4 - A AND 5 - B
Adding column --> 4- D AND 5- F
How can I write query?
Now that you've completely changed the original tables, this should be a simple JOIN.
SELECT t2.id, t1.name, t1.surname, t2.SchoolNumber, t2.ClassNumber, t2.ClassBranch
FROM Student1 AS t1
JOIN Student2 AS t2 ON t1.name = t2.name AND t1.surname = t2.surname
DEMO
To get those results?
1) The complicated way. By joining them.
SELECT
s2.ID,
s1.Name, s1.Surname,
s2."School Number", s2."Class Number", s2.ClassBranch
FROM Student1 AS s1
JOIN Student2 AS s2 ON (s2.Name = s1.Name AND s2.Surname = s1.Surname)
WHERE s1."Class Number" IN (4, 5);
2) The simple way, select only from the 2nd table
SELECT *
FROM Student2
WHERE "Class Number" IN (4, 5);
Test on SQL Fiddle here