SQL Query to categorize results of separate query - sql

I am trying to run a query on the results of a separate query to update the Route_Type column for each record based on unique Route_Code and Delivery_Day. For each distinct Route_Code from the select query, the Route_Type should be updated based on the following logic:
if there are no records for a specific Route_Code where Delivery_Day = 'Mon' then Route_Type should update to 'A'
if there are no records for a specific Route_Code where Delivery_Day = 'Sat' then Route_Type should update to 'B'
If there are no records for a specific Route_Code where Delivery_Day = 'Mon' OR 'Sat' then Route_Type should be 'TBD'
Else Route_Type = 'Both.'
Data:
Record Route_Code Delivery_Day Route_Type
1 112 Mon
2 112 Thur
3 112 Sat
4 112 Sun
5 113 Tue
6 113 Fri
7 113 Sat
8 113 Sun
9 113 Wed
Select Query:
Select Distinct Route_Code
From Deliveries;
Results:
Route_Code
1 112
2 113
The query should return all unique Route_Code and the calculated Route_Type for each, shown below...
Desired Query Result:
Route_Code Route_Type
1 112 Both
2 113 A
As a follow-up, I want all Route_Codes that have fewer than 1 month of records to display 'TBD.' The logic I have so far is
When
Max(sum(case when Delivery_Day= 'Mon' then 1 else 0 end),
sum(case when Delivery_Day= 'Tue' then 1 else 0 end),
sum(case when Delivery_Day= 'Wed' then 1 else 0 end),
sum(case when Delivery_Day= 'Thu' then 1 else 0 end),
sum(case when Delivery_Day= 'Fri' then 1 else 0 end),
sum(case when Delivery_Day= 'Sat' then 1 else 0 end),
sum(case when Delivery_Day= 'Sun' then 1 else 0 end)
Then 'TBD'
I realize that the native Max() function handles only single arguments, and am wondering where to go from here.

This sounds like aggregation. I find your logic a bit hard to follow. If I understand correctly, "B" has a Monday delivery and "A" has a Saturday. The logic looks like this:
select route_code,
(case when sum(case when Delivery_Day = 'Mon' then 1 else 0 end) > 0 and
sum(case when Delivery_Day = 'Sat' then 1 else 0 end) > 0
then 'Both'
when sum(case when Delivery_Day = 'Mon' then 1 else 0 end) > 0
then 'B'
when sum(case when Delivery_Day = 'Sat' then 1 else 0 end) > 0
then 'A'
else 'TBD'
end) as route_type
from delivies
group by route_code

Related

SQL count when equation of two columns are true

I have a sheet with rows (id and year). See below:
id
year
101
2002
101
2006
101
2010
101
2014
101
2018
102
2002
102
2006
102
2010
102
2014
103
2010
I simply want to regroup and reformat my table to look like this:
id
2002
2006
2010
2014
2018
101
1
1
1
1
1
102
1
1
1
1
0
103
0
0
1
0
0
In other words, whenever there is an id with a specific year it will show as a "1" in a field corresponding to that year. Note, that in the sheet there are no other years than the ones above.
I have managed to get the sheet reformatted by
select
id,
null as '2002', null as '2006', null as '2010',
null as '2014', null as '2018'
from
year_sheet
order by
id
But how to count and fill in the values for each year I don't find any solution.
Can someone help?
Thanks
You can use conditional aggregation:
SELECT id
, COUNT(CASE WHEN year = 2002 THEN 1 END) AS "2002"
, COUNT(CASE WHEN year = 2006 THEN 1 END) AS "2006"
, COUNT(CASE WHEN year = 2010 THEN 1 END) AS "2010"
, COUNT(CASE WHEN year = 2014 THEN 1 END) AS "2014"
, COUNT(CASE WHEN year = 2018 THEN 1 END) AS "2018"
FROM t
GROUP BY id
ORDER BY id
SQL Fiddle
try using case statement (Conditional statements)
select id,
case when year=2002 then 1 else 0 end as "2002",
case when year=2006 then 1 else 0 end as "2006",
case when year=2010 then 1 else 0 end as "2010",
case when year=2014 then 1 else 0 end as "2014",
case when year=2018 then 1 else 0 end as "2018"
from table
order by id
assuming that you would like to make the flags as 1 and 0 if the year appears for the id (for every id year appears only once).
In case if you want to count them (for eery id year appears more than once) then try using sum(case when....) as follows
select id,
sum(case when year=2002 then 1 else 0 end)as "2002",
sum(case when year=2006 then 1 else 0 end)as "2006",
sum(case when year=2010 then 1 else 0 end)as "2010",
sum(case when year=2014 then 1 else 0 end)as "2014",
sum(case when year=2018 then 1 else 0 end)as "2018"
from table
group by id
order by id

how to make pivot more than one column value sql

I have this table
country weeek quantity 1 quantity 2 quantity 3
0 1 sa 3235 365 123
1 1 su 6698 32135 1234
2 1 mo 1565 5689 12345
Desired output:
country sa_q1 su_q1 mo_q1 sa_q2 su_q2 mo_q2 sa_q3 su_q3 mo_q3
0 1 3235 6698 1565 365 32135 5689 123 1234 12345
Just use conditional aggregation:
select country,
sum(case when week = 'sa' then quantity1 else 0 end) as sa1,
sum(case when week = 'su' then quantity1 else 0 end) as su1,
sum(case when week = 'mo' then quantity1 else 0 end) as mo1,
sum(case when week = 'sa' then quantity2 else 0 end) as sa2,
sum(case when week = 'su' then quantity2 else 0 end) as su2,
sum(case when week = 'mo' then quantity2 else 0 end) as mo2,
sum(case when week = 'sa' then quantity3 else 0 end) as sa3,
sum(case when week = 'su' then quantity3 else 0 end) as su3,
sum(case when week = 'mo' then quantity3 else 0 end) as mo3
from t
group by country;

PostgreSQL transpose rows in to columns

i have one query
select department_id,SUM(quantity) as Quantity,sales_report.date as Date from sales_report where date = '2018-10-04' GROUP BY department_id , Date ORDER BY department_id ASC;
which gives me output like below:
id quantity date
1 204 2018-10-04
2 88 2018-10-04
3 135 2018-10-04
4 72 2018-10-04
5 391 2018-10-04
6 134 2018-10-04
7 386 2018-10-04
8 421 2018-10-04
9 292 2018-10-04
10 86 2018-10-04
11 83 2018-10-04
12 34 2018-10-04
13 3435 2018-10-04
but I need data like this:
id 1 2 3 4 5 6 7 8 9 10 11 12 13
2018-10-04 204 88 135 72 391 134 386 421 292 86 83 34 3435
Can anyone help me to achieve this..
you can try this:
select sales_report.date,
sum(case when id=1 then quantity else 0 end) as '1',
sum(case when id=2 then quantity else 0 end) as '2',
sum(case when id=3 then quantity else 0 end) as '3',
sum(case when id=4 then quantity else 0 end) as '4',
sum(case when id=5 then quantity else 0 end) as '5',
sum(case when id=6 then quantity else 0 end) as '6',
sum(case when id=7 then quantity else 0 end) as '7',
sum(case when id=8 then quantity else 0 end) as '8',
sum(case when id=9 then quantity else 0 end) as '9',
sum(case when id=10 then quantity else 0 end) as '10',
sum(case when id=11 then quantity else 0 end) as '11',
sum(case when id=12 then quantity else 0 end) as '12',
sum(case when id=13 then quantity else 0 end) as '13'
from sales_report where date = '2018-10-04' GROUP BY Date ORDER BY date ASC
you need case when, from your output data set you could do this pivoting
select date, max(case when id=1 then quantity end) as 1_one,
max(case when id=2 then quantity end) as 2_one,
max(case when id=3 then quantity end) as 3_one,
max(case when id=4 then quantity end) as 4_one,
max(case when id=5 then quantity end) as 5_one,
max(case when id=6 then quantity end) as 7_one,
max(case when id=7 then quantity end) as 7_one,
max(case when id=10 then quantity end) as 10_ten from t
group by date

Group by datepart and find total count of individual values of each record

This is table structure;
ID Score Valid CreatedDate
1 A 1 2018-02-19 23:33:10.297
2 C 0 2018-02-19 23:32:40.700
3 B 1 2018-02-19 23:32:30.247
4 A 1 2018-02-19 23:31:37.153
5 B 0 2018-02-19 23:25:08.667
...
I need to find total number of each score and valid in each month
I mean final result should be like
Month A B C D E Valid(1) NotValid(0)
January 123 343 1021 98 12 1287 480
February 516 421 321 441 421 987 672
...
This is what I tried;
SELECT DATEPART(year, CreatedDate) as Ay,
(select count(*) from TableResults where Score='A') as 'A',
(select count(*) from TableResults where Score='B') as 'B',
...
FROM TableResults
group by DATEPART(MONTH, CreatedDate)
but couldn't figure how to calculate all occurrence of scores on each month.
Use conditional aggregation.
SELECT DATEPART(year, CreatedDate) as YR
, DATEPART(month, CreatedDate) MO
, sum(Case when score = 'A' then 1 else 0 end) as A
, sum(Case when score = 'B' then 1 else 0 end) as B
, sum(Case when score = 'C' then 1 else 0 end) as C
, sum(Case when score = 'D' then 1 else 0 end) as D
, sum(Case when score = 'E' then 1 else 0 end) as E
, sum(case when valid = 1 then 1 else 0 end) as Valid
, sum(case when valid = 0 then 1 else 0 end) as NotValid
FROM TableResults
GROUP BY DATEPART(MONTH, CreatedDate), DATEPART(year, CreatedDate)
I'm not a big fan of queries in the select; I find they tend to cause performance problems in the long run. Since we're aggregating here I just applied the conditional logic to all the columns.

SQL count and group by date and type

I have a quality system table. There are 2 types of quality points NCR and RMA.
RMA is external and NCR is internal. We log transactions to the table either as a NCR or a RMA. I would like to have a query that will count all of the RMA's and all of the NCR's then group them by monthly count. For example:
MONTH RMA NCR
JANUARY 10 54
FEBRUARY 48 22
MARCH 25 55
If the value is zero for the month or the month has not yet come up, I don't want to see it on the report.
the table. this is what I have.
SELECT MONTH(QualityControl.CreateDate) MONTH, COUNT(*) AS 'NCR'
FROM QualityControl
WHERE YEAR(QualityControl.CreateDate)=2015
and
QualityControl.NCR is not null
GROUP BY MONTH(QualityControl.CreateDate)
This only gives me the month number (1=January) and the NCR count for that month.
Then I tried the following:
SELECT
SUM(CASE datepart(month,CreateDate) WHEN 1 THEN 1 ELSE 0 END) AS 'January',
SUM(CASE datepart(month,CreateDate) WHEN 2 THEN 1 ELSE 0 END) AS 'February',
SUM(CASE datepart(month,CreateDate) WHEN 3 THEN 1 ELSE 0 END) AS 'March',
SUM(CASE datepart(month,CreateDate) WHEN 4 THEN 1 ELSE 0 END) AS 'April',
SUM(CASE datepart(month,CreateDate) WHEN 5 THEN 1 ELSE 0 END) AS 'May',
SUM(CASE datepart(month,CreateDate) WHEN 6 THEN 1 ELSE 0 END) AS 'June',
SUM(CASE datepart(month,CreateDate) WHEN 7 THEN 1 ELSE 0 END) AS 'July',
SUM(CASE datepart(month,CreateDate) WHEN 8 THEN 1 ELSE 0 END) AS 'August',
SUM(CASE datepart(month,CreateDate) WHEN 9 THEN 1 ELSE 0 END) AS 'September',
SUM(CASE datepart(month,CreateDate) WHEN 10 THEN 1 ELSE 0 END) AS 'October',
SUM(CASE datepart(month,CreateDate) WHEN 11 THEN 1 ELSE 0 END) AS 'November',
SUM(CASE datepart(month,CreateDate) WHEN 12 THEN 1 ELSE 0 END) AS 'December',
SUM(CASE datepart(year,CreateDate) WHEN 2015 THEN 1 ELSE 0 END) AS 'TOTAL'
FROM
QualityControl
WHERE
CreateDate BETWEEN '2015/01/01' AND '2015/12/30'
And it gave me the count for NCR and RMA
Let's go with your first attempt, which is one row per value. You want to count the valid "NCR" and "RMA" values. You can use a COUNT() like this:
SELECT MONTH(qc.CreateDate) as MON, COUNT(NCR) as NCR, COUNT(RMA) as RMA
FROM QualityControl qc
WHERE CreateDate >= '2015-01-01' AND CreateDate < '2016-01-01'
GROUP BY MONTH(qc.CreateDate)
ORDER BY MON;
With a column (or other expression), COUNT() counts the number of non-NULL values. That seems to be exactly what you want.
If you wanted the SUM() of the values, then you would use SUM() instead of COUNT().
Note about the dates:
The version using comparisons is better than the one using YEAR(), because it can make use of indexes.
I changed the BETWEEN to >= and <. This version works correctly, if your date/time column has a time component. It also works for dates.
December has 31 days.
in sql server you can do all of these :
SELECT
CASE datepart(month,getdate()) WHEN 1 THEN 1 ELSE 0 END AS January,
CASE datepart(month,getdate()) WHEN 2 THEN 1 ELSE 0 END AS "February",
CASE datepart(month,getdate()) WHEN 3 THEN 1 ELSE 0 END AS [March]
the best method would be
SELECT datename(month, getdate())