Case statement problem to show values without null in a row - sql

select CASE WHEN ( rtt.us_code = 's' )
THEN rtt.name
ELSE '' END AS input_tax_name,
CASE WHEN ( rtt2.us_code = 'r')
THEN rtt2.name
ELSE '' END AS output_tax_name,
CASE WHEN ( rtt.us_code = 's' )
THEN rtt.acc_id
ELSE 0 END AS input_tax_rate,
CASE WHEN ( rtt2.us_code = 'r')
THEN rtt2.acc_id
ELSE 0 END AS output_tax_rate
from supplier_item si
JOIN ret_tx_type rtt
ON si.ret_tx_type_id = rtt.ret_tx_type_id
JOIN ret_tx_type rtt2
ON si.ret_tx_type_id = rtt2.ret_tx_type_id
where si.ret_tx_type_id is not null
I am trying to display input and output tax in the same row for a report depends on us_code is 'r' and 's'.
But i am getting the results like
if input tax is there ...output tax column will be null
if output tax is there ...input tax column will be null
i am want to get the both in same row and no need to make null in any rows
please help

SELECT
MAX(CASE rtt.us_code WHEN 's' THEN rtt.name END) AS input_tax_name,
MAX(CASE rtt.us_code WHEN 'r' THEN rtt.name END) AS output_tax_name,
MAX(CASE rtt.us_code WHEN 's' THEN rtt.acc_id END) AS input_tax_rate,
MAX(CASE rtt.us_code WHEN 'r' THEN rtt.acc_id END) AS output_tax_rate
FROM supplier_item si
INNER JOIN ret_tx_type rtt
ON si.ret_tx_type_id = rtt.ret_tx_type_id
GROUP BY ??? /* here you should supply a column,
presumably in 'si', that is common
to both of the related 'r'- and
's'-tax records */

You need to add a GROUP BY to your query on something (possibly GROUP BY si.id?)
And put the CASE statements into aggregates. e.g.
MAX(CASE WHEN ( rtt2.us_code = 'r')
THEN rtt2.acc_id
ELSE 0 END)

Related

Need help to simplify this T-SQL query

I have this working T-SQL query, is there any way to simplify it?
The SELECT COUNT(*) FROM Tablename is repeating and only the condition is different for each query, so is there a way to simplify this more? thank you
SELECT COUNT(*) FROM Table
WHERE columnA = 'I' AND columnB = 'I' AND columnC =''
UNION ALL
SELECT COUNT(*) FROM Table
WHERE columnA = 'I' AND columnB = 'I' AND columnC <>''
UNION ALL
SELECT COUNT(*) FROM Table
WHERE columnA IN ('A','R') AND columnB = 'I' AND columnD IN (SELECT columnE FROM Table2)
UNION ALL
SELECT COUNT(*) FROM Table
WHERE columnA IN ('B') AND columnB = 'I'
UNION ALL
SELECT COUNT(*) FROM Table
WHERE columnA IN ('R') AND columnB = 'S'
UNION ALL
SELECT COUNT(*) FROM Table
WHERE columnA IN ('A') AND columnB = 'S'
This is the working query and my output is 6 rows, want to maintain that
Let me assume that BI_BRH is unique in STDHOST. This is not strictly necessary but it are simplifying.
Then you can use conditional aggregation. I think putting the values in columns is the simplest approach:
SELECT SUM(CASE WHEN STATUS = 'I' AND TRX_STATE = 'I' AND ASSIGN_TO = '' THEN 1 ELSE 0 END),
SUM(CASE WHEN STATUS = 'I' AND TRX_STATE = 'I' AND ASSIGN_TO <>'' THEN 1 ELSE 0 END)
SUM(CASE WHEN STATUS IN ('A','R') AND TRX_STATE = 'I' AND s.BI_BRH IS NOT NULL THEN 1 ELSE 0 END)
SUM(CASE WHEN STATUS IN ('B') AND TRX_STATE = 'I' THEN 1 ELSE 0 END)
SUM(CASE WHEN STATUS IN ('R') AND TRX_STATE = 'S' THEN 1 ELSE 0 END)
SUM(CASE WHEN STATUS IN ('A') AND TRX_STATE = 'S' THEN 1 ELSE 0 END)
FROM ICSCHQINFO i LEFT JOIN
STDHOST s
ON s.BI_BRH = i.BRH_ASSIGN_TO;
Your code runs 6 times over the same table, with different conditions in the WHERE clause and returns 6 rows.
Assuming that the 6 conditions you have are mutually exclusive, you can create a CTE that returns for each row the category that it belongs to and then aggregate on that category:
WITH cte AS (
SELECT CASE
WHEN STATUS = 'I' AND TRX_STATE = 'I' AND ASSIGN_TO = '' THEN 'cat1'
WHEN STATUS = 'I' AND TRX_STATE = 'I' AND ASSIGN_TO <> '' THEN 'cat2'
WHEN STATUS IN ('A','R') AND TRX_STATE = 'I' AND BRH_ASSIGN_TO IN (SELECT BI_BRH FROM STDHOST) THEN 'cat3'
WHEN STATUS IN ('B') AND TRX_STATE = 'I' THEN 'cat4'
WHEN STATUS IN ('R') AND TRX_STATE = 'S' THEN 'cat5'
WHEN STATUS IN ('A') AND TRX_STATE = 'S' THEN 'cat6'
END category
FROM ICSCHQINFO
)
SELECT category, COUNT(*) counter
FROM cte
GROUP BY category
If there are no rows for any of the categories and in that case you want a row with 0, you need another CTE that returns the categories and LEFT join to the other CTE:
WITH
categories AS (SELECT category FROM (VALUES ('cat1'), ('cat2'), ('cat3'), ('cat4'), ('cat5'), ('cat6')) v(category)),
cte AS (
SELECT CASE
WHEN STATUS = 'I' AND TRX_STATE = 'I' AND ASSIGN_TO = '' THEN 'cat1'
WHEN STATUS = 'I' AND TRX_STATE = 'I' AND ASSIGN_TO <> '' THEN 'cat2'
WHEN STATUS IN ('A','R') AND TRX_STATE = 'I' AND BRH_ASSIGN_TO IN (SELECT BI_BRH FROM STDHOST) THEN 'cat3'
WHEN STATUS IN ('B') AND TRX_STATE = 'I' THEN 'cat4'
WHEN STATUS IN ('R') AND TRX_STATE = 'S' THEN 'cat5'
WHEN STATUS IN ('A') AND TRX_STATE = 'S' THEN 'cat6'
END category
FROM ICSCHQINFO
)
SELECT c.category, COUNT(t.category) counter
FROM categories c LEFT JOIN cte t
ON t.category = c.category
GROUP BY c.category

Pivot, CONCAT, one table and INNER JOIN with another table to create single table

Im having hard time in creating mysql table in which i want to pivot one table and concat its columns after pivoting and then INNER JOIN it with another table to create single table.
SELECT
data_id,
Max(case
when name = 'ApplicantsFirstName' then value else '' end ) as ApplicantsFirstName,
Max(case
when name = 'ApplicantsMiddleName' then value else '' end ) as ApplicantsMiddleName,
Max(case
when name = 'ApplicantsLastName' then value else '' end) as ApplicantsLastName,
Max(case
when name = 'FathersFirstName' then value else '' end) as FathersFirstName,
Max(case
when name = 'FathersLastName' then value else '' end ) as FathersLastName,
Max(case
when name = 'Gender' then value else '' end ) as Sex,
Max(case
when name = 'checkbox' then value else '' end ) as Approval,
Max(case
when name = 'url' then value else '' end ) as url,
Max(case
when name = 'text' then value else '' end ) as Information
FROM wphl_cf7_data_entry
GROUP by data_id
this query displayng the table now I need to CONCAT names and INNER JOIN with another table.
I would suggest using conditional aggregation, which I think is:
select data_id,
max(case when name = 'ApplicantsFirstName' then value end) as ApplicantsFirstName,
max(case when name = 'ApplicantsMiddleName' then value end) as ApplicantsMiddleName,
max(case when name = 'ApplicantsLastName' then value end) as ApplicantsLastName
from wphl_cf7_data_entry
group by data_id;
This will also work in both MySQL and SQL Server (the original database tags).

Need to create a Totals report from oracle table data

I have a table in oracle similar to the the example table image that I need to have output the segregated totals as shown in the second example results image.
I need the sums of each item_type where A & B are just examples for a large number of possible items that can be added.
example table:
example results:
Any help would be appreciated. thanks
Use conditional aggregation:
SELECT
store,
SUM(CASE WHEN item_type = 'A' AND item_status = 'IN' THEN 1 ELSE 0 END) a_items_in,
SUM(CASE WHEN item_type = 'A' AND item_status = 'OUT' THEN 1 ELSE 0 END) a_items_out,
SUM(CASE WHEN item_type = 'B' AND item_status = 'IN' THEN 1 ELSE 0 END) b_items_in,
SUM(CASE WHEN item_type = 'B' AND item_status = 'OUT' THEN 1 ELSE 0 END) b_items_out
FROM mytable
GROUP BY store

case statement to find one value

I'm trying to show one row per id but it is returning three.
If the id has a 'y' then it should show a 'y'.
If it shows a 'y' and 'r' it should be 'y'.
If it has 'y', 'r', 'n' it should be 'y'.
If it is just id and 'r' it should be 'r' and id and just 'n' then 'n'.
I can't seem to get it to work using a case statement. Any ideas? Thanks.
I've tried this:
,CASE WHEN result = 'Y' THEN 'Y'
WHEN result = 'Y' AND result = 'R') THEN 'Y'
WHEN result = 'R' THEN 'R'
ELSE 'N' END AS CARE_PLAN
What it is returning:
ID result
3434 'y'
3434 'r'
3434 'n'
You can use Listagg function,
Writing a subquery and DISTINCT then use Listagg function.
SELECT id, Listagg (result, ', ')
within GROUP (ORDER BY result) as CARE_PLAN
FROM (SELECT DISTINCT id,
( CASE
WHEN result = 'Y' THEN 'Y'
WHEN result = 'Y'
AND result = 'R' THEN 'Y'
WHEN result = 'R' THEN 'R'
ELSE 'N'
END ) AS result
FROM t) T
GROUP BY id
sqlfiddle:http://sqlfiddle.com/#!4/02cd5/2
[Results]:
| ID | CARE_PLAN |
|------|-----------|
| 1234 | N, R, Y |
It shall be proper to use ASCII and CHR functions for your case instead of using CASE .. WHEN, as in the following :
SELECT ID, CHR(MAX(ASCII(result))) AS CARE_PLAN
FROM TAB
GROUP BY ID
ORDER BY ID;
SQL Fiddle Demo
You would seem to want aggregation with some conditional logic:
select id,
(case when sum(case when result = 'y' then 1 else 0 end) > 0 then 'y'
when sum(case when result = 'r' then 1 else 0 end) > 0 then 'r'
when min(result) = max(result) and min(result) = 'n' then 'n'
else '?'
end) as new_result
from t
group by id;
If there are only those three values, then perhaps this simplified logic works:
select id, max(result) as new_result
from t
group by id;

counting records on the same table with different values possibly none sql server 2008

I have a inventory table with a condition i.e. new, used, other, and i am query a small set of this data, and there is a possibility that all the record set contains only 1 or all the conditions. I tried using a case statement, but if one of the conditions isn't found nothing for that condition returned, and I need it to return 0
This is what I've tried so far:
select(
case
when new_used = 'N' then 'new'
when new_used = 'U' then 'used'
when new_used = 'O' then 'other'
end
)as conditions,
count(*) as count
from myDB
where something = something
group by(
case
when New_Used = 'N' then 'new'
when New_Used = 'U' then 'used'
when New_Used = 'O' then 'other'
end
)
This returns the data like:
conditions | count
------------------
new 10
used 45
I am trying to get the data to return like the following:
conditions | count
------------------
new | 10
used | 45
other | 0
Thanks in advance
;WITH constants(letter,word) AS
(
SELECT l,w FROM (VALUES('N','new'),('U','used'),('O','other')) AS x(l,w)
)
SELECT
conditions = c.word,
[count] = COUNT(x.new_used)
FROM constants AS c
LEFT OUTER JOIN dbo.myDB AS x
ON c.letter = x.new_used
AND something = something
GROUP BY c.word;
try this -
DECLARE #t TABLE (new_used CHAR(1))
INSERT INTO #t (new_used)
SELECT t = 'N'
UNION ALL
SELECT 'N'
UNION ALL
SELECT 'U'
SELECT conditions, ISNULL(r.cnt, 0) AS [count]
FROM (
VALUES('U', 'used'), ('N', 'new'), ('O', 'other')
) t(c, conditions)
LEFT JOIN (
SELECT new_used, COUNT(1) AS cnt
FROM #t
--WHERE something = something
GROUP BY new_used
) r ON r.new_used = t.c
in output -
new 2
used 1
other 0
You can do it as a cross-tab:
select
sum(case when new_used = 'N' then 1 else 0 end) as N,
sum(case when new_used = 'U' then 1 else 0 end) as U,
sum(case when new_used = 'O' then 1 else 0 end) as Other
from myDB
where something = something