sql select data with multiple arguments - sql

i stuck with this problem, please help!
Here is the problem:
I have a catalog and line detail table. Such as;
Line detail table: TRANSACTIONS_LINE_DETAIL catalog table: CATALOG
In TRANSACTIONS_LINE_DETAIL table: SQ_TRANSACTION_LINE_DETAIL_ID, RF_TRANSACTION_ID, CH_ITEM_CODE,.. columns are included.
In CATALOG table: CH_ITEM_CODE, CH_ITEM_NAME,.. columns are included. (CH_ITEM_CODE is unique)
TRANSACTIONS_LINE_DETAIL table and CATALOG table relates each other by their CH_ITEM_CODE columns.
So my problem is;
I wanna write a query that fetches me transaction ids (RF_TRANSACTION_ID) which has X,Y and Z item names together. (CH_ITEM_NAME).
Below code couldn't help me;
SELECT RF_TRANSACTION_ID
FROM TRANSACTIONS_LINE_DETAIL TLD, CATALOG CAT
WHERE TLD.CH_ITEM_CODE= CAT.CH_ITEM_CODE
AND CAT.CH_ITEM_NAME IN ('X', 'Y', 'Z')
GROUP BY RF_WO_ID
HAVING COUNT(1) = 3
The query should fetch me transaction ids that can have;
X, Y, Z
or
A, B, C, X, Y, Z
or
X, Y, Z, P
but NOT
X
or
X, Y
or
Z, Y, A, B

You need to move the condition to the having clause:
SELECT RF_TRANSACTION_ID
FROM TRANSACTIONS_LINE_DETAIL TLD join
CATALOG CAT
on TLD.CH_ITEM_CODE = CAT.CH_ITEM_CODE
where cat.ch_item_name in ('X', 'Y', 'Z')
GROUP BY RF_TRANSACTION_ID
HAVING sum(case when CAT.CH_ITEM_NAME = 'X' then 1 else 0 end) > 0 and
sum(case when CAT.CH_ITEM_NAME = 'Y' then 1 else 0 end) > 0 and
sum(case when CAT.CH_ITEM_NAME = 'Z' then 1 else 0 end) > 0;
This is an example of a "set-within-sets" query. I like doing these with the logic in the having clause, because it makes it more general.
This version includes a where clause, which (in your case) makes the query more efficient.
Each condition in the having clause is counting the row that match a particular condition.
To add Q, for instance, is quite easy (this condition is in your query but not in the sample results):
SELECT RF_TRANSACTION_ID
FROM TRANSACTIONS_LINE_DETAIL TLD join
CATALOG CAT
on TLD.CH_ITEM_CODE = CAT.CH_ITEM_CODE
GROUP BY RF_TRANSACTION_ID
HAVING sum(case when CAT.CH_ITEM_NAME = 'X' then 1 else 0 end) > 0 and
sum(case when CAT.CH_ITEM_NAME = 'Y' then 1 else 0 end) > 0 and
sum(case when CAT.CH_ITEM_NAME = 'Z' then 1 else 0 end) > 0 and
sum(case when CAT.CH_ITEM_NAME = 'Q' then 1 else 0 end) > 0;
If you wanted to find transactions with X, Y, Z, but not Q, the last condition would be = 0.

Related

How to convert a single column containing multiple rows into rows

I have a column , says name Student_name and its values lets say, A, B, C, D, E, F and so on..
Now i have to convert this column into row with each alias.
select A.counts from (
select count(b.ATTND_FLAG) as counts , b.ATTND_FLAG as ATTND_FLAG
from hr_emp_notifications a, v_emp_attendance b
where a.emp_id=b.emp_id
and a.emp_id=90327
and b.ATTND_FLAG is not null
group by b.ATTND_FLAG )A
my query showing one column which has multiple values in rows.
i have to convert these values into row.
I would use conditional aggregation:
select sum(case when ea.attnd_flag = 'A' then 1 else 0 end) as num_a,
sum(case when ea.attnd_flag = 'B' then 1 else 0 end) as num_b,
sum(case when ea.attnd_flag = 'C' then 1 else 0 end) as num_c,
sum(case when ea.attnd_flag = 'D' then 1 else 0 end) as num_d,
sum(case when ea.attnd_flag = 'E' then 1 else 0 end) as num_e,
sum(case when ea.attnd_flag = 'F' then 1 else 0 end) as num_f
from v_emp_attendance ea
where ea.emp_id = 90327;
If you want multiple employees, use group byea.emp_id`.
Notice that the join is not needed.
It seems you need a pivot clause here -
SELECT *
FROM (SELECT NAME, ATTND_FLAG
FROM v_emp_attendance)
PIVOT (COUNT(ATTND_FLAG)
FOR NAME IN ('A' AS A, 'B' AS B, 'C' AS C /* AND SO ON */)
)

SQL : Group by and check if all, some or none are set

Lets say I have the following table:
FKEY A B C D E F
'A' 1 0 1 0 1 0
'A' 0 1 1 1 0 0
Now i want to make a group by FKEY but I just want to know if the A-F columns has 1 in one, all or none of the grouped rows.. The resulton the above table would be:
FKEY A B C D E F
'A' S S A S S N
..where S is "some", A is "all" and N is "none".
What would be the best approach to make this query. I could so some nested queries, but isnt there a smarter way?
In my real life data, the 1's and 0's are actually DATETIME and NULL's
You can use case and aggregation:
select fkey,
(case when sum(a) = 0 then 'N'
when sum(a) = count(*) then 'A'
else 'S'
end) as a,
(case when sum(b) = 0 then 'N'
when sum(b) = count(*) then 'A'
else 'S'
end) as b,
. . .
from t
group by fkey;
The above assumes that the values are only 0 and 1. If that is the case, you can actually phrase this as:
(case when max(a) = 0 then 'N'
when min(a) = 1 then 'A'
else 'S'
end) as a,
You mentioned that your 0 and 1 are actually null or non null dates. Here's a modified version of Gordon's query that caters for that:
select fkey,
(case when count(datecol) = 0 then 'all dates are null'
when count(datecol) = count(*) then 'all dates are filled'
else 'some are null, some filled'
end) as a,
...
from t
group by fkey;
COUNT(null) is 0, COUNT('2001-01-01') is 1, COUNT(*) is the row count independent of any variable. Hence, if our count of the dates was 0, all must be null. If the count of the dates was equal to the count of the rows, then all must be filled with some value, otherwise it's a mix

How do I check if a certain value exists?

I have a historization table called CUR_VALID. This table looks something like this:
ID CUR_VALID
1 N
1 N
1 Y
2 N
2 Y
3 Y
For every ID there needs to be one Y. If there is no Y or multiple Y there is something wrong. The statment for checking if there are multiple Y I already got. Now I only need to check for every ID if there is one Y existing. Im just not sure how to do that. This is what I have so far. So how do I check if the Value 'Y' exists?
SELECT Count(1) [Number of N]
,MAX(CUR_VALID = 'N')
,[BILL_ID]
,[BILL_MONTH]
,[BILL_SRC_ID]
FROM db.dbo.table
GROUP BY [BILL_ID]
,[BILL_MONTH]
,[BILL_SRC_ID]
Having MAX(CUR_VALID = 'N') > 1
Why are you fiddling with 'N' when you are interested in 'Y'?
Use conditional aggregation to get the count of the value your are interested in.
SELECT
COUNT(*) AS number_of_all,
COUNT(CASE WHEN cur_valid = 'Y' THEN 1 END) AS number_of_y,
COUNT(CASE WHEN cur_valid = 'N' THEN 1 END) AS number_of_n,
bill_id,
bill_month,
bill_src_id,
FROM db.dbo.table
GROUP BY bill_id, bill_month, bill_src_id;
Add a HAVING clause in order to get only valid
HAVING COUNT(CASE WHEN cur_valid = 'Y' THEN 1 END) = 1
or invalid
HAVING COUNT(CASE WHEN cur_valid = 'Y' THEN 1 END) <> 1
bills.
The following query will give you the list of id for which your integrity condition is not met: For every ID there needs to be one Y. If there is no Y or multiple Y there is something wrong.
select T1.id from table T1 where (select count(*) from table T2 where T2.id=T1.id and T2.CUR_VALID='Y')!=1
This query returns both not having at least one 'Y' value and more than one 'Y' value ID's.
First, sum up the Y values and relate to each id, then select not 1 ones from that table.
select * from (
select ID, SUM(case when CUR_VALID = 'Y' then 1 else 0 end) as CNT
from table
group by ID
) b where b.CNT <> 1
DBFiddle
As I understand, you want to get all the id for which your integrity check passes. And integrity check for you means, there is only one row with CUR_VALID value equal to Y in the CUR_VALID table.
This can be achieved by a group by clause:
select id from CUR_VALID
where CUR_VALID.CUR_VALID = 'Y'
group by id
having count(CUR_VALID.CUR_VALID) = 1;

Display Default Value Decode Oracle SQL

I am attempting to set values to zero if a user does not exist in one of my tables. Currently, I am using decode to count the number of users that meet a certain criteria and then display the result.
SELECT T.D_CODE,
T.C_NO,
SUM(DECODE(t.Value, 'A', 1, 0)) AS FirstValue,
SUM(DECODE(t.Value, 'B', 1, 0)) AS SecondValue,
SUM(DECODE(t.Value, 'C', 1, 0)) AS ThirdValue,
SUM(DECODE(t.Value, 'F', 1, 0)) AS LastValue
FROM Table T,
Table OtherTable S
WHERE T.T_SSN = S.SSN(+)
AND T.D_CODE = 'INF'
GROUP BY t.D_CODE,
T.C_NO;
The issue is that I have a third table (TT) that has additional values in it. If TT has a value that is not present in Table T, then I need to display that record with 0's for all of the Decode values.
Required output would look something like:
D_CODE, C_NO, FirstValue, SecondValue, ThirdValue, LastValue
INF 600 2 0 0 0
INF 501 0 0 1 0
INF 400 0 0 0 0
Where INF 400 does not exist in Table t, only in Table TT
Any suggestions?
Your problem is that you are filtering the users by T.D_CODE = 'INF' which means that any user that does not met that criteria will not come at all in the results. So, for what I understood of your question you need this:
SELECT T.D_CODE,
T.C_NO,
SUM(CASE WHEN T.D_CODE = 'INF' AND t.Value = 'A' THEN 1 ELSE 0 END) AS FirstValue,
SUM(CASE WHEN T.D_CODE = 'INF' AND t.Value = 'B' THEN 1 ELSE 0 END) AS AS SecondValue,
SUM(CASE WHEN T.D_CODE = 'INF' AND t.Value = 'C' THEN 1 ELSE 0 END) AS AS ThirdValue,
SUM(CASE WHEN T.D_CODE = 'INF' AND t.Value = 'D' THEN 1 ELSE 0 END) AS AS LastValue
FROM Table T
LEFT JOIN Table OtherTable S
ON T.T_SSN = S.SSN
LEFT JOIN AnotherTable TT
ON T.T_SSN = TT.SSN
GROUP BY t.D_CODE,
T.C_NO;
Since you didn't provide any more details about your TT table I just guessed the relation between it and the T table.
Side note: Always use the SQL ANSI [LEFT ]JOINs style.
ALSO Note that for your current query and current fetched fields tables S and TT are totally irrelevant, unless you didn't explain it right.

Select count of unique values that might appear in different columns

I am trying to get a count on values that might appear in 3 different columns but only require the count of unique values. Microsoft SQL.
Eg. value X might appear in column A, B, or C or all 3 but need to make sure I only get a unique count of value X no matter what columns it comes under.
Thanks!
If you want to count each individual occurrence of X in any column A, B, or C, then the following should work:
SELECT
SUM(CASE WHEN A = 'X' THEN 1 ELSE 0 END) +
SUM(CASE WHEN B = 'X' THEN 1 ELSE 0 END) +
SUM(CASE WHEN C = 'X' THEN 1 ELSE 0 END)
FROM yourTable
Is this what you are looking for? This will Count only 1 occurrence per row regardless of how many columns it is found in.
SELECT
ID
,SUM(CASE WHEN ColA = 'X' OR ColB = 'X' OR ColC = 'X' THEN 1 ELSE 0 END) AS ValueCount
FROM
TABLENAME
GROUP BY
ID
I guess I should show it without the group by too because you don't specify a grouping.
SELECT
,SUM(CASE WHEN ColA = 'X' OR ColB = 'X' OR ColC = 'X' THEN 1 ELSE 0 END) AS ValueCount
FROM
TABLENAME