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

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

Related

How to display total count in descending order but group by id

i have the following codes which displays the following result
select distinct
srcaccountid,
srccharid,
srccharname,
action,
itemname,
sum(itemcount) over (partition by srccharname, itemname)
as total_count,
sum(price) over(partition by srccharname, itemname)
as total_price
from
itemlog
where
action = 6
and logtime >='2023-02-13'
order by
total_count desc,
srcaccountid
the result is as follows
srcaccountid srccharid srccharname action itemname total_count total_price
1 21 abc 6 dog 2222 231
2 22 sdd 6 cat 1234 122
1 21 abc 6 cat 324 77
1 21 abc 6 mouse 122 32
2 22 sdd 6 mouse 12 3
i will like the result to show as follow
srcaccountid srccharid srccharname action itemname total_count
total_price
1 21 abc 6 dog 2222 231
1 21 abc 6 cat 324 77
1 21 abc 6 mouse 122 32
2 22 sdd 6 cat 1234 122
2 22 sdd 6 mouse 12 3
i cant seem to be able to show the highest sales amount while grouping the ids together and not splitting them up
Change the order by. Put the srcaccountid first.
order by
srcaccountid,
total_count desc

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 query to allow NULL for a highest_bid column when no bid has been placed yet

For school I need to make a function on an auction website. For this I need to join a couple of tables in a VIEW. This worked just fine, until I needed to add a filter for price range. Seems easy enough but the query result needs to allow a NULL when no bid has been placed.
The Statement for the View:
SELECT I.itemID, I.title, I.startPrice, B.highestBid, Cfi.category, I.endDate
FROM dbo.Items AS I INNER JOIN dbo.category_for_item AS Cfi ON V.itemID = Vir.itemID
LEFT OUTER JOIN dbo.Bid AS B ON V.itemID = B.itemID
This would get the following Table:
itemID title startPrice highestBid category endDate
1 1234 Alfa 25 26 PC 2018-09-22
2 1234 Alfa 25 NULL PC 2018-09-22
3 5678 Bravo 9 20 Console 2018-07-03
4 5678 Bravo 9 15 Console 2018-07-03
5 5678 Bravo 9 NULL Console 2018-07-03
6 9876 Charlie 84 100 Stamps 2018-06-14
7 9876 Charlie 84 90 Stamps 2018-06-14
8 9876 Charlie 84 85 Stamps 2018-06-14
9 9876 Charlie 84 NULL Stamps 2018-06-14
10 1470 Delta 98 100 Fashion 2018-06-15
11 1470 Delta 98 99 Fashion 2018-06-15
12 1470 Delta 98 NULL Fashion 2018-06-15
13 9631 Echo 56 65 Cars 2018-06-25
14 9631 Echo 56 NULL Cars 2018-06-25
15 7856 Foxtrot 98 NULL Dolls 2018-12-26
After looking around for answers I got a query for joining the VIEW on itself with only showing the highest bid instead of all bids:
SELECT VW.itemID, VW.title, VW.startPrice, VW.highestBid, VW.category, VW.endDate
FROM VW_SEARCH AS VW
INNER JOIN (SELECT itemID, MAX(highestBid) AS MaxBid
FROM VW_SEARCH
GROUP BY itemID) VJ
ON VW.itemID = VJ.itemID AND VW.highestBid = VJ.MaxBid
This gave the next results:
itemID title startPrice highestBid category endDate
1 1234 Alfa 25 26 PC 2018-09-22
2 5678 Bravo 9 20 Console 2018-07-03
3 9876 Charlie 84 85 Stamps 2018-06-14
4 1470 Delta 98 100 Fashion 2018-06-15
5 9631 Echo 56 65 Cars 2018-06-25
As I expected the result only showed the items with at least one bid on them. I tried added one extra condition on the subQuery and Joining RIGHT OUTER to make sure I would not get doubles of an itemID.
SELECT VW.itemID, VW.title, VW.startPrice, VW.highestBid, VW.category, VW.endDate
FROM VW_SEARCH AS VW
RIGHT OUTER JOIN (SELECT itemID, MAX(highestBid) AS MaxBid
FROM VW_SEARCH
WHERE highestBid > 0 OR highestBid IS NULL
GROUP BY itemID) VJ
ON VW.itemID = VJ.itemID AND VW.highestBid = VJ.MaxBid
This gave the following results (did not add result 5 - 1199 because it is all the same as result 4, this would happen in the actual table not the example table from above):
itemID title startPrice highestBid category endDate
1 1234 Alfa 25 26 PC 2018-09-22
2 5678 Bravo 9 20 Console 2018-07-03
3 9876 Charlie 84 85 Stamps 2018-06-14
4 NULL NULL NULL NULL NULL NULL
1200 1470 Delta 98 100 Fashion 2018-06-15
1201 9631 Echo 56 65 Cars 2018-06-25
While this is technicly allowing a NULL in the colums I need to get a result in the likes of :
itemID title startPrice highestBid catgory endDate
1 1234 Alfa 25 26 PC 2018-09-22
2 5678 Bravo 9 20 Console 2018-07-03
3 9876 Charlie 84 85 Stamps 2018-06-14
4 1470 Delta 98 100 Fashion 2018-06-15
5 9631 Echo 56 65 Cars 2018-06-25
6 7856 Foxtrot 98 NULL Dolls 2018-12-26
How do I get the desired result, or is it just impossible?
Also if the query could be written better, please say so.
Thanks in advance.
Solve the problem using a left join:
SELECT VW.itemID, VW.title, VW.startPrice, VW.highestBid, VW.category, VW.endDate
FROM VW_SEARCH VW LEFT JOIN
(SELECT itemID, MAX(highestBid) AS MaxBid
FROM VW_SEARCH
GROUP BY itemID
) VJ
ON VW.itemID = VJ.itemID AND VW.highestBid = VJ.MaxBid;
Or, use the ANSI-standard ROW_NUMBER() function:
select vw.*
from (select vw.*,
row_number() over (partition by itemID
order by highestBid nulls last
) as seqnum
from vw_search vw
) vw
where seqnum = 1;
This guarantees one row per item.
Note: Not all databases support NULLS LAST. This may not even be necessary, but you can also implement it using a case expression.
Can you give the definition of the view at least? Maybe the table definition too.
I would go only with subquery as because identity column :
select vw.*
from vw_search vw
where id = (select vm1.id
from vw_search vm1
where vm.itemID = vw1.itemID and vm1.highestBid is not null
order by vm1.highestBid desc
limit 1
);
However, some DBMS has not support LIMIT clause such as SQL Server if so, then you can use TOP clause instead.

How do I change my SQL SELECT GROUP BY query to show me which records are missing a value?

I have a list of codes by area and type. I need to get the unique codes for each type, which I can do with a simple SELECT query with a GROUP BY. I now need to know which area does not have one of the codes. So how do I run a query to group by unique values and tell me how records do not have one of the values?
ID Area Type Code
1 10 A 123
2 10 A 456
3 10 B 789
4 10 B 987
5 10 C 654
6 10 C 321
7 20 A 123
8 20 B 789
9 20 B 987
10 20 C 654
11 20 C 321
12 30 A 137
13 30 A 456
14 30 B 579
15 30 B 789
16 30 B 987
17 30 C 654
18 30 C 321
I can run this query to group them by type and get get the unique codes:
SELECT tblExample.Type, tblExample.Code
FROM tblExample
GROUP BY tblExample.Type, tblExample.Code
This gives me this:
Type Code
A 123
A 137
A 456
B 579
B 789
B 987
C 321
C 654
Now I need to know which areas do not have a given code. For example, Code 123 does not appear for Area 10 and code 137 does not appear for codes 10 and 20. How do I write a query to give me that areas are missing a code? The format of the output doesn't matter, I just need to get the results. I'm thinking the results could be in one column or spread out in multiple columns:
Type Code Missing Areas or Missing1 Missing2
A 123 30 30
A 137 10, 20 10 20
A 456 20 20
B 579 10, 20 10 20
B 789
B 987
C 321
C 654
You can get a list of the missing code/areas by first generating all combinations and then filtering out the ones that exist:
select t.type, c.code
from (select distinct type from tblExample) t cross join
(select distinct code from tblExample) c left join
tblExample e
on t.type = e.type and c.code = e.code
where e.type is null;

Need to join three tables. Not sure which join fits the req

table 1
AcctNO CustomerId Role Name
1 123 A ABC
2 121 B BCA
3 321 C CBA
table 2
AcctNo CustomerId Role Address
1 123 A 1/12
2 121 B 11/3
4 231 C 12-1
3 321 C 111
5 221 C 121
table 3
AcctNo CustomerId Role CompanyName
4 231 C hello
5 221 C bello
3 321 C cello
output should be as follows
AcctNo CustomerId Role Name Address COmpanyName
1 123 A ABC 1/12 NULL
2 121 B BCA 11/3 NULL
3 321 C CBA 111 cello
4 231 C NULL 12-1 hello
5 221 C NULL 121 bello
Use a left join between the tables on a unique column like the CustomerID.
A left join is used instead of a inner join so you get any missing values as a null instead of missing a record.