SQL select where records match in two fields - sql

TABLE:A
acctno, ratcod, ssno
select only records where ssno is the same and ratcod contains any of 6,7,8 and the same ssno is found elsewhere to contain ratcod value <> 6,7,8
DATA TABLE A
acctno ratcod ssno
123456 6 123-44-5566
23456 4 123-44-5566
12345 1 123-44-5566
654321 6 333-44-5566
664433 6 222-44-5566
222336 2 123-44-5566
554646 4 444-98-9876
DESIRED OUTPUT
acctno ratcod ssno
123456 6 123-44-5566
23456 4 123-44-5566
12345 1 123-44-5566
222336 2 123-44-5566
Trying the following produces an error
DB2 for i5/OS]SQL0199 - Keyword IN not expected.
select tableA.*
from (select ssno from refdat1.lnmast lnmast
group by lnmast.ssno
having sum(case ratcod in (6, 7 ,8) then 1 else 0 end) > 0
and sum(case ratcod in (6, 7, 8) then 0 else 1 end) > 0)
as ASum
JOIN tableA
ON tableA.ssno = ASum.ssno

The logic is: find all ssnos having a ratcod in (6, 7, 8) and having a ratcod not in (6, 7, 8). Once these are found, return all the rows with that ssno.
select tableA.*
from (select ssno
from tableA
group by ssno
having sum(case ratcod in (6, 7, 8) then 1 else 0 end) > 0
and sum(case ratcod in (6, 7, 8) then 0 else 1 end) > 0)
as ASum
JOIN TableA
ON TableA.ssno = ASum.ssno

Related

DB2 SQL to count number of rows with respective to 2 columns

I have data in DB2 table something like this
main_id
sub_id
key_id
type
100
1001
1
0
100
1001
2
0
101
1002
1
0
102
1003
1
1
102
1004
1
1
103
1005
2
2
103
1006
2
2
104
1007
2
0
105
1008
2
1
105
1009
2
1
Now I am trying to create output something like this where :
count1 - main_id count with multiple rows only with key id 1
count2 - main_id count with multiple rows only with key id 2
count3 - main_id count with multiple rows with combo 1 & 2 key id
Type
count_1
count_2
count_3
0
1
1
1
1
2
1
Overall, I need distinct main_id's count with multiple rows of sub_id and then need to segregate them based on type and key_id's
In the above case :
100 - has 2 rows w/ 1001 but key_id's are differnt -count_3
102 - has 2 rows w/ 1002 and 1003 but key_id's are from 1 - count_1
103 - has 2 rows w/ 1005 and 1006 but key_id's are from 2 - count_2
105 - has 2 rows w/ 1008 and 1009 but key_id's are from 2 -count_2
Ignored 101 and 104 as there are no multiple rows for that main_id
WITH main_ids AS (
SELECT main_id, key_id, type, COUNT(sub_id) sub_id_count
FROM your_table
GROUP BY main_id, key_id, type
),
grouped AS (
SELECT type, COUNT(main_id) main_id_count
FROM main_ids
WHERE sub_id_count > 1
GROUP BY type
)
SELECT type,
SUM(CASE WHEN key_id = 1 THEN sub_id_count END) count_1,
SUM(CASE WHEN key_id = 2 THEN sub_id_count END) count_2,
SUM(CASE WHEN sub_id_count > 1 THEN sub_id_count END) count_3
FROM main_ids
JOIN grouped ON grouped.type = main_ids.type
GROUP BY type
Need help with count_3 condition, is there any way where can get count of main_id having multiple rows with both key_id 1 and 2(in the above case only 100 main_id is satisfying that condition)
Appreciate any help
WITH
T (main_id, sub_id, key_id, type) AS
(
VALUES
(100, 1001, 1, 0)
, (100, 1001, 2, 0)
, (101, 1002, 1, 0)
, (102, 1003, 1, 1)
, (102, 1004, 1, 1)
, (103, 1005, 2, 2)
, (103, 1006, 2, 2)
, (104, 1007, 2, 0)
, (105, 1008, 2, 1)
, (105, 1009, 2, 1)
)
, G AS
(
SELECT TYPE, KEY_ID, COUNT (DISTINCT MAIN_ID) C
FROM T
GROUP BY TYPE, KEY_ID
)
SELECT
TYPE
, CASE WHEN C1 = 1 THEN 1 END AS COUNT_1
, CASE WHEN C2 = 1 THEN 1 END AS COUNT_2
, CASE WHEN C1 > 1 AND C2 > 1 THEN 1 END AS COUNT_3
-- Just for convenience
, C1
, C2
FROM
(
SELECT
M.TYPE
, COALESCE (G1.C, 0) AS C1
, COALESCE (G2.C, 0) AS C2
FROM (SELECT DISTINCT TYPE FROM G) M
LEFT JOIN G G1 ON G1.TYPE = M.TYPE AND G1.KEY_ID = 1
LEFT JOIN G G2 ON G2.TYPE = M.TYPE AND G2.KEY_ID = 2
)
TYPE
COUNT_1
COUNT_2
COUNT_3
C1
C2
0
1
2
2
1
1
1
1
1
2
1
0
1

Count and GROUP values from a CASE expression

Trying to count the total number of wins and total times a horse finished in the top 6 and GROUP by the order of favouritism in a horse racing market.
I am referencing this answer since it is looking for a similar outcome Count the occurrences of DISTINCT values
I have tried this expression but when executed, it returns the same number in both case columns
ie;
SPFav WinsByFavouritism PlaceByFavouritism
1 4143 4143
2 3963 3963
3 3853 3853
This is the code I am running - what is causing this?
SELECT SPFav,
COUNT(CASE WHEN FinishingPosition = 1 THEN 1 ELSE 0 END) as WinsByFavouritism,
COUNT(CASE WHEN FinishingPosition <= 6 THEN 1 ELSE 0 END) as PlaceByFavouritism
FROM [NRaceHistory].[dbo].[EachWayBetting]
GROUP BY SPFav
ORDER BY SPFav ;
Working with the first comment this would give the following possible solution.
Sample data
create table EachWayBetting
(
SPFav int,
FinishingPosition int
);
insert into EachWayBetting (SPFav, FinishingPosition) values
(1, 1),
(1, 2),
(1, 2),
(1, 9),
(2, 7),
(2, 8),
(2, 2),
(2, 1);
Solution
SELECT SPFav,
COUNT(CASE WHEN FinishingPosition = 1 THEN 1 END) as WinsByFavouritism,
COUNT(CASE WHEN FinishingPosition <= 6 THEN 1 END) as PlaceByFavouritism
FROM EachWayBetting
GROUP BY SPFav
ORDER BY SPFav
Result
SPFav WinsByFavouritism PlaceByFavouritism
----- ----------------- ------------------
1 1 3
2 1 2
Fiddle
I believe you should replace COUNT in your query with SUM. i.e. it should be:
SELECT SPFav,
SUM(CASE WHEN FinishingPosition = 1 THEN 1 ELSE 0 END) as WinsByFavouritism,
SUM(CASE WHEN FinishingPosition <= 6 THEN 1 ELSE 0 END) as PlaceByFavouritism
FROM [NRaceHistory].[dbo].[EachWayBetting]
GROUP BY SPFav
ORDER BY SPFav;

How to achieve this output?

I have a table with data like this :
create table test (transferID int, customerNumber varchar(10), txnstatus int);
insert into test
values
(1, 1001, 1),
(2, 1001, 2),
(3, 1001, 1),
(4, 1002, 2),
(5, 1002, 1),
(6, 1002, 2),
(7, 1002, 1),
(8, 1002, 1),
(9, 1003, 2),
(10, 1003, 1),
(11, 1003, 1),
(12, 1003, 1),
(13, 1003, 1),
(14, ' ', 1),
(15, ' ', 2),
(16, NULL, 2);
and the excepted output is to display the fields with customer number, total number of txns for each customer, successfulTxns, failedTxns. Note that:
txnStatus 1 and 2 represent "success" and "fail" respectively.
customer number may be empty or NULL in some cases like last three rows
This is how I tried, but didn't get the excepted result
select customerNumber,
count(*) over (partition by 1) as TotalTxns,
case when txnstatus = 1 then count(txnstatus) else 0 end as successFulTrxn,
case when txnstatus = 2 then count(txnstatus) else 0 end as failedFulTrxn
from test
group by customerNumber, txnstatus
I expect the output to be:
CustNumber TotalTxns SuccessFulTxns FailedTxns
1001 3 2 1
1002 5 3 2
1003 5 4 1
2 1 1
NULL 1 0 1
Your logic is somewhat correct, you just need to put the CASE expression inside COUNT, not the other way round:
SELECT customerNumber
, COUNT(*) AS TotalTxns
, COUNT(CASE WHEN txnstatus = 1 THEN 1 END) AS SuccessFulTxns
, COUNT(CASE WHEN txnstatus = 2 THEN 1 END) AS FailedTxns
FROM test
GROUP BY customerNumber
Note that there is not such thing as empty INT. Empty strings/whitespace becomes 0 when converted to INT.
Instead of blank I inserted 0 as customerNumber is int. If you want the same order as expected result, If you need 0 and NULL at the end, you can use conditional orderby.
SELECT customerNumber
, COUNT(*) AS TotalTxns
, COUNT(CASE WHEN txnstatus = 1 THEN 1 END) AS successFulTrxn
, COUNT(CASE WHEN txnstatus = 2 THEN 1 END) AS failedFulTrxn
FROM test
GROUP BY customerNumber
ORDER BY CASE WHEN customerNumber IS NULL THEN 100000
WHEN customerNumber = 0 THEN 99999
ELSE customerNumber END
Conditional aggregation is the way to achieve this :
select customerNumber, count(transferID) as TotalTxns,
sum(case when txnstatus = 1 then 1 else 0 end) as successFulTrxn,
sum(case when txnstatus = 2 then 1 else 0 end) as failedFulTrxn
from test t
group by customerNumber;
If you have to do a grouping action on txnstatus, you obviously can't include that field in the grouping list.
Furthermore, you can't do the count inside the case, you have to do it outside, and you don't have to count the status, because if the status is '2', the result will be clearly uncorrect.
I would approach the problem as below.
select customerNumber, count(*) as TotalTxns,
sum(case when txnstatus = 1 then 1 else 0 end) as successFulTrxn,
sum(case when txnstatus = 2 then 1 else 0 end) as failedFulTrxn
from test
group by customerNumber
It gives to me the results you are looking for.

Total Sum and Partial Sum

I am currently using SSMS. I am pulling data, and trying to get two different columns that sum prices. The two columns 'ChangeSpend' and 'TotalSpend' both reference the same column and this is where I am running into problems.
I want ChangeSpend to return the sum of all the codes per receipt that start with V.Ch% (so they exclude all the others) and the TotalSpend to sum all of the codes for each receipt.
Here is my current code:
SELECT
Receipt
,ReceiptCode
,ReceiptAmount
,sum(ReceiptAmount) over (Partition by Receipt) as TotalSpend
,(CASE WHEN ReceiptCode = 'V.Ch%' then sum(ReceiptAmount)
over (Partition by Receipt)
ELSE 0
END) as ChangeSpend
FROM tableA
LEFT OUTER JOIN tableB
on A.Receipt = B.Receipt
WHERE ReceiptCode LIKE 'V.%'
ORDER BY Receipt
However, my query currently prints this:
Receipt ReceiptCode ReceiptAmount TotalSpend ChangeSpend
1 v.cha 5 20 0
1 v.rt 2 20 0
1 v.chb 6 20 0
1 v.abc 7 20 0
2 v.cha 20 21 0
2 v.abc 1 21 0
3 v.cha 4 14 0
3 v.chb 1 14 0
3 v.tye 7 14 0
3 v.chs 2 14 0
And I would like it to print this:
Receipt ReceiptCode ReceiptAmount TotalSpend ChangeSpend
1 v.cha 5 20 11
1 v.rt 2 20 11
1 v.chb 6 20 11
1 v.abc 7 20 11
2 v.cha 20 21 20
2 v.abc 1 21 20
3 v.cha 4 14 7
3 v.chb 1 14 7
3 v.tye 7 14 7
3 v.chs 2 14 7
Thanks for any help
Try
,SUM(CASE WHEN ReceiptCode LIKE 'V.Ch%' THEN ReceiptAmount ELSE 0 END)
OVER (Partition by Receipt)
AS ChangeSpend
You have to put the SUM outside the CASE, not the other way around:
SUM(CASE WHEN SomeCondition=true THEN MyColumn ELSE 0 END)
This may help:
Create Table Payment(
Receipt Int,
ReceiptCode VARCHAR(10),
ReceiptAmount decimal)
Insert Into Payment
Values
(1, 'v.cha', 5),
(1, 'v.rt', 2),
(1, 'v.chb', 6),
(1, 'v.abc', 7),
(2, 'v.cha', 20),
(2, 'v.abc', 1),
(3, 'v.cha', 4),
(3, 'v.chb', 1),
(3, 'v.the', 7),
(3, 'v.chs', 2);
SELECT * ,
SUM(ReceiptAmount) OVER ( PARTITION BY Receipt ) AS TotalSpend ,
SUM(IIF(ReceiptCode LIKE 'v.ch%',ReceiptAmount,0)) OVER ( PARTITION
BY Receipt ) AS ChangeSpend
FROM payment;
Result:
SUM(
CASE WHEN ReceiptCode like 'V.Ch%' then ReceiptAmount ELSE 0 END) as ChangeSpend

Different select criteria in odd and even events

I have a table which looks like this ( 10 billion rows)
AID BID CID
1 2 1
1 6 9
0 1 4
1 3 2
1 100 2
0 4 2
0 0 1
The AID could only be 0 or 1. BID and CID could be anything.
Now I want to select events first with AID=1 and then AID=0, and again AID=1 and then AID=0.
The idea is to select equal numbers of AID=1 and AID=0 event.
How can I achieve that?
The expected result is
AID BID CID
1 2 1
0 1 4
1 6 9
0 4 2
1 3 2
0 0 1
;WITH cte AS (
select *
FROM (VALUES
(1, 2, 1),
(1, 6, 9),
(0, 1, 4),
(1, 3, 2),
(1, 100, 2),
(0, 4, 2),
(0, 0, 1)
) as t(AID, BID, CID)
),
withrow AS (
SELECT ROW_NUMBER() OVER (PARTITION BY AID ORDER BY AID) as RN, *
FROM cte)
SELECT AID,BID,CID
FROM withrow
ORDER BY RN asc , aid desc
Output:
AID BID CID
----------- ----------- -----------
1 100 2
0 4 2
1 3 2
0 1 4
1 6 9
0 0 1
1 2 1
(7 row(s) affected)