Combining rows with NULL columns - sql

select
COUNT(Table1.ID) as count_shipped,
null as count_shipped
from Table1
where
table1.saleStatus='shipped'
and table1.saleApproved='yes'
union
select
null,
COUNT(Table1.ID) as count_pending
from Table1
where
table1.saleStatus in ('Pending', 'awaiting payment', 'backorder')
This gives this output
count_shipped count_shipped
NULL 5
4 NULL
but I don't want Null I only want 4 5 in one line Can anybody help me how to do this sql server?

You can use a case to sum up your conditions
select sum(case when saleStatus = 'shipped' and table1.saleApproved = 'yes'
then 1
else 0
end) as count_shipped,
sum(case when saleStatus in ('Pending', 'awaiting payment', 'backorder')
then 1
else 0
end) as count_pending
from Table1

Related

SQL query several columns about the same field but diferent codes

How can I create a query that has multiple counter columns for the same field?
I have a field called card_status that can have 7 different values.
I wanted to create a query that would display total values on the same row and not on 7 different rows.
SELECT SUM(CASE WHEN card_status = 1 THEN 1 ELSE 0 END) as Count_of_1,
SUM(CASE WHEN card_status = 2 THEN 1 ELSE 0 END) as Count_of_2,
...
SUM(CASE WHEN card_status = 7 THEN 1 ELSE 0 END) as Count_of_7
FROM your_table;
You could use a conditional count
For example:
SELECT col1, col2
, COUNT(CASE WHEN card_status = 'revoked' THEN card_status END) AS TotalRevoked
, COUNT(CASE WHEN card_status = 'requested' THEN card_status END) AS TotalRequested
, COUNT(CASE WHEN card_status = 'lost' THEN card_status END) AS TotalLost
-- add more
, COUNT(*) AS Total
FROM YourTable t
GROUP BY col1, col2
ORDER BY col1, col2
This works on the principle that counting a column or expression doesn't count the NULL's

Group by several columns with count on another column SQL Server

I'm using SQL SERVER 2012 and I'm struggling with this SQL statement. Basically I have this table
table
I want to group by Date, and Username, with a count on the status column, like below :
query result
How can I achieve this?
You can use an aggredated query with a few conditional SUMs.
SELECT
LastUpdate,
UpdatedBy as User,
SUM(CASE WHEN Status = 'A' THEN 1 ELSE 0 END) as A
SUM(CASE WHEN Status = 'C' THEN 1 ELSE 0 END) as C
SUM(CASE WHEN Status = 'D' THEN 1 ELSE 0 END) as D
SUM(CASE WHEN Status = 'Z' THEN 1 ELSE 0 END) as Z
SUM(CASE WHEN Status = 'X' THEN 1 ELSE 0 END) as X
FROM table
GROUP BY LastUpdate, UpdatedBy
ORDER BY LastUpdate, UpdatedBy
You can try using conditional aggregation
select LastUpdate,UpdatedBy,
count(case when Status='A' then UpdatedBy end) as 'A',
count(case when Status='C' then UpdatedBy end) as 'C',
count(case when Status='D' then UpdatedBy end) as 'D',
count(case when Status='Z' then UpdatedBy end) as 'Z',
count(case when Status='X' then UpdatedBy end) as 'X'
from tablename
group by LastUpdate,UpdatedBy
Ok I figured it out with help from the guys answers
SELECT
CAST(LastUpdate as DATE),
UserName,
SUM(CASE WHEN Status = 1 THEN 1 ELSE 0 END) as [Status_1],
SUM(CASE WHEN Status = 2 THEN 1 ELSE 0 END) as [Status_2],
SUM(CASE WHEN Status = 3 THEN 1 ELSE 0 END) as [Status_3]
FROM Table
WHERE LastUpdate BETWEEN '2018-11-30 10:013:44.080' AND '2018-12-30 10:013:44.080'
GROUP BY CAST(LastUpdate as DATE), UserName
ORDER BY CAST(LastUpdate as DATE)
This is a sample query where I'm looking for records between two dates. The problem I was having was in part due to filtering on datetime rather than date. The lastupdate column is a datetime so by casting to date it solved the issue

Comparing values in two columns and returning values on conditional bases using sql hive

I have two columns, I want to get an output based on a comparative basis of both. My data is somewhat like:
Customer Id status
100 A
100 B
101 B
102 A
103 A
103 B
So a customer can have a status A or B or both, I have to segrerate them on customer id basis for a status. If status A and B then return happy, if only A, return Avg and if only B return Sad.
try the below query,
SELECT DISTINCT Customer_Id,
(CASE WHEN COUNT(*) OVER(PARTITION BY Customer_Id) > 1 THEN 'happy'
WHEN Tstatus = 'A' THEN 'Avg'
ELSE 'Sad'END) AS New_Status
FROM #table1
GROUP BY Customer_Id,Tstatus
if Customer Id and status is a unique combination then
STEP 1: use case to determine a or b
SELECT customer id
,CASE WHEN avg(case when [status] ='A' then 0 else 2 end)
FROM [Your Table]
group by[customer id]
and step 2 will be casing avg into result: like this
SELECT customer id
,CASE WHEN (avg(case when [status] ='A' then 0 else 2 end)) = 1 THEN 'happy' ELSE WHEN (avg(case when [status] ='A' then 0 else 2 end)) = 0 THEN 'Avg' ELSE 'Sad' END
FROM [Your Table]
group by[customer id]
I would do this simply as:
select customer_id,
(case when min(status) <> max(status) then 'happy'
when min(status) = 'A' then 'avg'
else 'sad'
end)
from t
where status in ('A', 'B')
group by customer_id

group by and select max with value null

I have a next problem with query
SELECT
T.DETALLE_BECA_ANIO anio,
T.DETALLE_BECA_MES mes,
T.DETALLE_BECA_NIVEL_EDU_ID edu_id,
T.DETALLE_BECA_TRAMO_ID tr_id,
MAX(
CASE
WHEN T.DETALLE_BECA_TIPO_BENE_ID IS NULL
THEN NVL(DETALLE_BECA_VALOR,0)
ELSE 0
END) mant ,
MAX(
CASE
WHEN T.DETALLE_BECA_TIPO_BENE_ID = 1
THEN NVL(DETALLE_BECA_VALOR,0)
ELSE 0
END) tras
FROM
(SELECT DETALLE_BECA_NIVEL_EDU_ID,
DETALLE_BECA_BECA_ID,
DETALLE_BECA_TIPO_BENE_ID,
DETALLE_BECA_VALOR,
DETALLE_BECA_MES,
DETALLE_BECA_REGION_ID,
DETALLE_BECA_PROVINCIA_ID,
DETALLE_BECA_ANIO,
DETALLE_BECA_TRAMO_ID,
DETALLE_BECA_COMUNA_ID
FROM TBL_DETALLE_BECAS
WHERE (DETALLE_BECA_TIPO_BENE_ID = 1
OR DETALLE_BECA_TIPO_BENE_ID IS NULL)
and DETALLE_BECA_BECA_ID = 1
and detalle_beca_mes = 3
) T
GROUP BY T.DETALLE_BECA_BECA_ID,
T.DETALLE_BECA_TRAMO_ID,
T.DETALLE_BECA_REGION_ID,
T.DETALLE_BECA_PROVINCIA_ID,
T.DETALLE_BECA_ANIO,
T.DETALLE_BECA_MES,
T.DETALLE_BECA_NIVEL_EDU_ID,
T.DETALLE_BECA_COMUNA_ID
ORDER BY T.DETALLE_BECA_BECA_ID,
T.DETALLE_BECA_MES,
T.DETALLE_BECA_NIVEL_EDU_ID
output:
"ANIO" "MES" "EDU_ID" "TR_ID" "MANT" "TRAS"
2017 3 2 0.62 0 NULL
2017 3 3 1.24 6 NULL
2017 3 NULL 1.0 NULL 1
I need that sum value where EDU_ID is null with value 2,3 in TR_ID and replace value null in "tras" with value from EDU is null
"ANIO" "MES" "EDU_ID" "TR_ID" "MANT" "TRAS"
2017 3 2 1.62 0 1
2017 3 3 2.24 6 1
I writed query with min(edu_id) or max(edu_id ) but could not solve my problem.
The other thing that occurred to me is to make a join with the same table
First, this makes more sense as your query:
SELECT T.DETALLE_BECA_ANIO as anio, T.DETALLE_BECA_MES as mes,
T.DETALLE_BECA_NIVEL_EDU_ID as edu_id, T.DETALLE_BECA_TRAMO_ID as tr_id,
MAX(CASE WHEN T.DETALLE_BECA_TIPO_BENE_ID IS NULL
THEN NVL(DETALLE_BECA_VALOR, 0)
ELSE 0
END) as mant ,
MAX(CASE WHEN T.DETALLE_BECA_TIPO_BENE_ID = 1
THEN NVL(DETALLE_BECA_VALOR,0)
ELSE 0
END) tras
FROM TBL_DETALLE_BECAS
WHERE (DETALLE_BECA_TIPO_BENE_ID = 1 OR DETALLE_BECA_TIPO_BENE_ID IS NULL) AND
DETALLE_BECA_BECA_ID = 1 AND
detalle_beca_mes = 3
GROUP BY T.DETALLE_BECA_ANIO, T.DETALLE_BECA_MES,
T.DETALLE_BECA_NIVEL_EDU_ID, T.DETALLE_BECA_TRAMO_ID
ORDER BY T.DETALLE_BECA_BECA_ID, T.DETALLE_BECA_MES, T.DETALLE_BECA_NIVEL_EDU_ID;
This eliminates the subquery (unnecessary) and only aggregates by the columns being returned. A proper query might fix your problem.
But, you seem to want to use NULL to be "all" for the other columns. If so, something like this will work:
WITH t as (
SELECT T.DETALLE_BECA_ANIO as anio, T.DETALLE_BECA_MES as mes,
T.DETALLE_BECA_NIVEL_EDU_ID as edu_id, T.DETALLE_BECA_TRAMO_ID as tr_id,
MAX(CASE WHEN T.DETALLE_BECA_TIPO_BENE_ID IS NULL
THEN NVL(DETALLE_BECA_VALOR, 0)
ELSE 0
END) as mant ,
MAX(CASE WHEN T.DETALLE_BECA_TIPO_BENE_ID = 1
THEN NVL(DETALLE_BECA_VALOR,0)
ELSE 0
END) tras
FROM TBL_DETALLE_BECAS
WHERE (DETALLE_BECA_TIPO_BENE_ID = 1 OR DETALLE_BECA_TIPO_BENE_ID IS NULL) AND
DETALLE_BECA_BECA_ID = 1 AND
detalle_beca_mes = 3
GROUP BY T.DETALLE_BECA_ANIO, T.DETALLE_BECA_MES,
T.DETALLE_BECA_NIVEL_EDU_ID, T.DETALLE_BECA_TRAMO_ID
)
SELECT t.ANIO, t.MES, t.EDU_ID,
COALESCE(t.TR_ID, 0) + COALESCE(tnull.TR_ID, 0) as TR_ID,
t.MANT,
COALESCE(t.TRAS, 0) + COALESCE(tnull.TRAS, 0) as TRAS
FROM t LEFT JOIN
(SELECT t.*
FROM t
WHERE t.edu_id IS NULL
) tnull
ON tnull.ANIO = t.ANIO AND tnull.MES = t.MES
WHERE t.edu_id IS NOT NULL
ORDER BY T.DETALLE_BECA_BECA_ID, T.DETALLE_BECA_MES, T.DETALLE_BECA_NIVEL_EDU_ID;

how to Sum "case when" clause after inner join without duplication

I am a new member of Stackoverflow (and also I'm a new of coding sql) if i do any mistakes about my question please advise me :)
I'm trying to get SUM of Amount in CASE WHEN Clause.
Here is my table
tableA
UserID transid Brand Amount
UserA 109974 MIX 960.00 --BrandMIX=A & B
UserB 109975 B 894.00
UserC 109976 C 350.00
UserC 109977 MIX 300.00 --BrandMIX=C & D
tableB
Row transid Brand
1 109974 A
2 109974 B
3 109975 B
4 109976 C
5 109977 C
6 109977 D
I tried inner join table a and table b on a.soid = b.soid
and when i SUM it, result was wrong due to duplication of transid in table b.
here is my coding.
SELECT UserID
,CASE WHEN COUNT(DISTINCT(b.transid )) <> 0 THEN COUNT(DISTINCT(b.transid ))
ELSE NULL END) AS 'Frequency'
,SUM(Amount) as 'TotalAmount'
,YEAR(transdatetime) AS 'Year'
,SUM (CASE [Brand] WHEN 'AA' THEN 1 ELSE 0 END) AS [BrandA]
,SUM (CASE [Brand] WHEN 'BB' THEN 1 ELSE 0 END) AS [BrandB]
,SUM (CASE [Brand] WHEN 'CC' THEN 1 ELSE 0 END) AS [BrandC]
,SUM (CASE [Brand] WHEN 'DD' THEN 1 ELSE 0 END) AS [BrandD]
,SUM (CASE [Brand] WHEN 'ZZ' THEN 1 ELSE 0 END) AS [BrandZ]
FROM tableA a
INNER tableB b ON a.transid = b.transid
WHERE is_paid = 'N'
GROUP BY UserID, YEAR(transdatetime)
Result that I got
Result that I want
I added ROW_NUMBER() into tableB, I want to SUM(Amount) WHERE MIN(ROW_NUMBER), is it impossible?
Please advise, thank you.
Based on your row_number i.e (row column of tableB) I have modified your query to take min(row) values. Please try this...If this does not work please post the complete tables structures.
SELECT UserID
,CASE WHEN COUNT(DISTINCT(b.transid )) <> 0 THEN COUNT(DISTINCT(b.transid ))
ELSE NULL END AS 'Frequency'
,SUM(Amount) as 'TotalAmount'
,YEAR(transdatetime) AS 'Year'
,SUM (CASE [Brand] WHEN 'AA' THEN 1 ELSE 0 END) AS [BrandA]
,SUM (CASE [Brand] WHEN 'BB' THEN 1 ELSE 0 END) AS [BrandB]
,SUM (CASE [Brand] WHEN 'CC' THEN 1 ELSE 0 END) AS [BrandC]
,SUM (CASE [Brand] WHEN 'DD' THEN 1 ELSE 0 END) AS [BrandD]
,SUM (CASE [Brand] WHEN 'ZZ' THEN 1 ELSE 0 END) AS [BrandZ]
FROM tableA a
INNER JOIN tableB b ON a.transid = b.transid
WHERE is_paid = 'N' AND b.row in (select min(row) from tableB group by transid)
GROUP BY UserID, YEAR(transdatetime)