Needing Help Separating Data into columns - sql

I'm currently using SQL at work to Query a database in order to display certain information. I have each item that's being pulled as separate entities. Whenever I run the Query my results only show under one column. Is there a way to separate this data into separate columns based on alias?
SELECT
count(o.orderid) AS Current_Daily
FROM
orders o
WHERE
o.ship_dt BETWEEN '2020-11-09 00:00:00' AND '2020-11-15 23:59:59'
AND o.orderstatus = 2
UNION
#UNION ALL
SELECT
count(o.orderid) AS Previous_Daily
FROM
orders o
WHERE
o.ship_dt BETWEEN '2019-11-09 00:00:00' AND '2019-11-15 23:59:59'
AND o.orderstatus = 2
UNION
#UNION ALL
SELECT
count(o.orderid) AS Current_Monthly
FROM
orders o
WHERE
o.ship_dt BETWEEN '2020-11-01 00:00:00' AND '2020-11-15 23:59:59'
AND o.orderstatus = 2
UNION
#UNION ALL
SELECT
count(o.orderid) AS Previous_Monthly
FROM
orders o
WHERE
o.ship_dt BETWEEN '2019-11-01 00:00:00' AND '2019-11-15 23:59:59'
AND o.orderstatus = 2
;
Any Help would be greatly appreciated.

Use conditional aggregation, as in:
select
sum(case when ship_dt >= '2020-11-09' and ship_dt < '2020-11-15' then 1 else 0 end) as current_daily,
sum(case when ship_dt >= '2020-11-01' and ship_dt < '2020-11-15' then 1 else 0 end) as current_monthly,
... -- more conditional "sum()"s if needed
from orders o
where orderstatus = 2

You probably just want conditional aggregation. Something like this:
SELECT SUM(CASE WHEN o.ship_dt >= '2020-11-09' AND o.ship_dt < '2020-11-16' THEN 1 ELSE 0 END) AS Current_Daily,
SUM(CASE WHEN o.ship_dt >= '2020-11-01' AND o.ship_dt < '2020-11-16' THEN 1 ELSE 0 END) AS Current_Monthly,
FROM orders o
WHERE o.orderstatus = 2;
You can add additional columns using similar logic.

Related

How do I include records in a Summary query to include those that don't have data?

I have a query on a transaction table that returns the Summarized total on a column for each ID based on a data range. The query works great except it doesn't include those IDs that don't have data in the transaction table. How can I include those IDs in my result filled with a zero total. Here's a simplified version of my query.
SELECT tblID.IDName
,SUM(CASE
WHEN tblTransactions.idxTransType = 30
THEN CAST(tblTransactions.TimeAmount AS FLOAT) / 60.0
ELSE 0
END) AS 'Vacation'
FROM tblTransactions
INNER JOIN tblTransTypes ON tblTransactions.idxTransType = tblTransTypes.IdxTransType
INNER JOIN tblID ON tblTransactions.idxID = tblID.IdxID
WHERE (tblTransactions.Deleted = 0)
AND (tblTransactions.NotCurrent = 0)
AND (tblTransactions.TransDate >= CONVERT(DATETIME, 'March 1, 2018', 102))
AND (tblTransactions.TransDate <= CONVERT(DATETIME, 'April 11, 2018', 102))
GROUP BY tblID.IDName
Actually it's slightly more complicated than that:
SELECT
i.IDName,
SUM(CASE WHEN t.idxTransType = 30 THEN CAST(t.TimeAmount AS FLOAT) / 60.0 ELSE 0 END) AS 'Vacation'
FROM
tblID i
LEFT JOIN tblTransactions t ON t.idxID = i.IdxID AND t.Deleted = 0 AND t.NotCurrent = 0 AND t.TransDate BETWEEN '20180301' AND '20180411'
LEFT JOIN tblTransTypes tt ON tt.IdxTransType = t.idxTransType
GROUP BY
i.IDName;
You want left joins:
SELECT i.IDName,
SUM(CASE WHEN t.idxTransType = 30 THEN CAST(t.TimeAmount AS Float) / 60.0 ELSE 0 END) AS Vacation
FROM tblID i LEFT JOIN
tblTransactions t
ON t.idxID = i.IdxID AND
t.Deleted = 0 AND
t.NotCurrent = 0 AND
t.TransDate >= '2018-03-01' AND
t.TransDate <= '2018-04-11'
tblTransTypes tt
ON t.idxTransType = tt.IdxTransType
GROUP BY i.IDName;
Notes:
Table aliases make the query much easier to write and to read.
Use ISO/ANSI standard date formats.
The filter conditions on all but the first table belong in the ON clauses.

Total Count of each

I have a problem with my SQL Server query.
My query must display the total number of each category. Not the total amount of all categories.
SELECT [CATEGORY],
(SELECT COUNT(*)
FROM [Group_New_DB].[dbo].[INCIDENTSM1]
WHERE ([OPEN_TIME] >= #StartDate and [OPEN_TIME] < #EndDate + 1) ) AS OpenedCount,
(SELECT COUNT(*)
FROM [Group_New_DB].[dbo].[INCIDENTSM1]
WHERE ([CLOSE_TIME] >= #StartDate and [CLOSE_TIME] < #EndDate + 1)) AS ClosedCount
FROM [Group_New_DB].[dbo].[INCIDENTSM1]
GROUP BY CATEGORY
ORDER BY CATEGORY
The report consists of a table with 3 columns: Category, Registered, Closed.
1 column is the category name.
2 column is how many categories have been registered.
3 column -> how many columns were closed.
But result
The result that turned out as a result does not look right.
I don't quite understand what is the difference between total number vs total amount as the question doesn't provide any context.
Although, if you are trying to get OpenedCount and ClosedCount as you have named the columns, I suggest you try below:
SELECT
CATEGORY,
SUM(CASE WHEN (OPEN_TIME >= #start_date AND OPEN_TIME < #end_date+1)
THEN 1
ELSE 0
END) AS OPENED_COUNT,
SUM(CASE WHEN (CLOSED_TIME >= #start_date AND CLOSED_TIME < #end_date+1)
THEN 1
ELSE 0
END) AS CLOSED_COUNT
FROM
[Group_New_DB].[dbo].[INCIDENTSM1]
GROUP BY
CATEGORY
ORDER BY
CATEGORY
IMO, This is also a better way as it doesn't include multiple sub-queries.
Correction: changed COUNT to SUM as suggested by TriV - Thanks!
Try this instead -
SELECT [CATEGORY],
COUNT(CASE WHEN [OPEN_TIME] >= #StartDate and [OPEN_TIME] < #EndDate + 1 THEN 1 ELSE NULL END) AS OpenedCount,
COUNT(CASE WHEN [CLOSE_TIME] >= #StartDate and [CLOSE_TIME] < #EndDate + 1 THEN 1 ELSE NULL END) AS ClosedCount
FROM [Group_New_DB].[dbo].[INCIDENTSM1] GROUP BY
CATEGORY ORDER BY CATEGORY

How to show 0 value using COUNT and SELECTon a SQL query

I have ONLY 1 table called Meeting that stores all meeting requests.
This table can be EMPTY.
It has several columns including requestType (which can only be "MT") meetingStatus (can only be either pending, approved, denied or canceled) and meetingCreatedTime
I want to count how many requests of each status's type (in other words how many requests are pending, how many are approved, denied and canceled) for the last 30 days
Problem is that if there is no request then nothing display but I want to display 0, how do I do it? Here is my query now:
SELECT [requestType],
( SELECT COUNT ([requestType]) FROM [Meeting] WHERE CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE) AND [meetingStatus] = 'Approved') As 'Approved',
( SELECT COUNT ([requestType]) FROM [Meeting] WHERE CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE) AND [meetingStatus] = 'Pending') As 'Pending',
( SELECT COUNT ([requestType]) FROM [Meeting] WHERE CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE) AND [meetingStatus] = 'Canceled') As 'Canceled',
( SELECT COUNT ([requestType]) FROM [Meeting] WHERE CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE) AND [meetingStatus] = 'Denied') As 'Denied'
FROM [Meeting]
WHERE CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE) GROUP BY [requestType]
Result:
What I want is:
SELECT
RT.requestType,
SUM(CASE WHEN M.meetingStatus = 'Approved' THEN 1 ELSE 0 END) AS Approved,
SUM(CASE WHEN M.meetingStatus = 'Pending' THEN 1 ELSE 0 END) AS Pending,
SUM(CASE WHEN M.meetingStatus = 'Canceled' THEN 1 ELSE 0 END) AS Canceled,
SUM(CASE WHEN M.meetingStatus = 'Denied' THEN 1 ELSE 0 END) AS Denied,
FROM
(SELECT DISTINCT requestType FROM Meeting) RT
LEFT OUTER JOIN Meeting M ON
M.requestType = RT.requestType AND
M.meetingCreatedTime >= DATEADD(DAY, -30, GETDATE())
GROUP BY
RT.requestType
The SUMs are a much clearer (IMO) and much more efficient way of getting the counts that you need. Using the requestType table (assuming that you have one) lets you get results for every request type even if there are no meetings of that type in the date range. The LEFT OUTER JOIN to the meeting table allows the request type to still show up even if there are no meetings for that time period.
All of your CASTs between date values seem unnecessary.
Move those subqueries into simple sum/case statements:
select rt.request_type,
sum(case when [meetingStatus] = 'Approved' then 1 else 0 end),
sum(case when [meetingStatus] = 'Pending' then 1 else 0 end),
sum(case when [meetingStatus] = 'Canceled' then 1 else 0 end),
sum(case when [meetingStatus] = 'Denied' then 1 else 0 end)
from ( select 'MT' ) rt (request_type) --hopefully you have lookup table for this
left
join [Meeting] m on
rt.request_type = m.request_type and
CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE)
group
by rt.request_type;
This is one possible approach to force one line to be visible in any case. Adapt this to your needs...
Copy it into an empty query window and execute... play around with the WHERE part...
DECLARE #Test TABLE (ID INT IDENTITY, GroupingKey VARCHAR(100));
INSERT INTO #Test VALUES ('a'),('a'),('b');
SELECT TOP 1 tbl.CountOfA
,tbl.CountOfB
,tbl.CountOfC
FROM
(
SELECT 1 AS Marker
,(SELECT COUNT(*) FROM #Test WHERE GroupingKey='a') AS CountOfA
,(SELECT COUNT(*) FROM #Test WHERE GroupingKey='b') AS CountOfB
,(SELECT COUNT(*) FROM #Test WHERE GroupingKey='c') AS CountOfC
WHERE (1=1) --play here with (1=0) and (1=1)
UNION ALL
SELECT 2,0,0,0
) AS tbl
ORDER BY Marker

Run a query consisting of subqueries only

I have a SQL query that only consists of sub queries, But I cannot run it I get an SQL error, What is the correct Syntax to run query consisting of sub queries only...?
Query:
SELECT COUNT(id) AS 'totalNumOfCustomers'
FROM customers
WHERE customers.isDemo =0
AND customers.isLead=0
AND regTime < '2012-01-01'
SELECT COUNT(id) AS 'totalNumOfCustomersPerMonth'
FROM customers
WHERE customers.isDemo =0
AND customers.isLead=0
AND regTime >='2012-01-01'
AND regTime < '2012-02-01'
SELECT COUNT(positions.id) AS 'totalPositions',
ROUND(SUM(amount),2) - ROUND(SUM(payout),2) AS 'grossIncome'
FROM positions
LEFT JOIN customers ON positions.customerId = customers.id
WHERE date >= '2012-01-01'
AND date < '2012-02-01'
AND customers.isDemo=0
AND customers.isLead=0
AND status != 'canceled'
I am running this in WorkBench, The error message is this:
Error Code: 1064. You Have an error in your SQL syntax
How about this
select
(SELECT COUNT(id)
FROM customers
WHERE customers.isDemo =0
AND customers.isLead=0
AND regTime < '2012-01-01') as totalNumOfCustomers,
(SELECT COUNT(id)
FROM customers
WHERE customers.isDemo =0
AND customers.isLead=0
AND regTime >='2012-01-01'
AND regTime < '2012-02-01') as totalNumOfCustomersPerMonth,
(SELECT COUNT(positions.id)
FROM positions
LEFT JOIN customers ON positions.customerId = customers.id
WHERE date >= '2012-01-01'
AND date < '2012-02-01'
AND customers.isDemo=0
AND customers.isLead=0
AND status != 'canceled') as totalPositions,
(SELECT ROUND(SUM(amount),2) - ROUND(SUM(payout),2)
FROM positions
LEFT JOIN customers ON positions.customerId = customers.id
WHERE date >= '2012-01-01'
AND date < '2012-02-01'
AND customers.isDemo=0
AND customers.isLead=0
AND status != 'canceled') as grossIncome;
I think you get error, because there is no ; ant the end of each query. No error message, so just guessing
The two first queries you can easily express as one query:
SELECT COUNT(case when regTime < '2012-01-01' end ) AS totalNumOfCustomers
, COUNT(case when >='2012-01-01' AND regTime < '2012-02-01' end ) AS totalNumOfCustomersPerMonth
FROM customers
WHERE customers.isDemo =0
AND customers.isLead=0 ;
As others have suggested you can then use a cross join to take the third query into play
You can run these queries by putting them in the from clause and combining them using CROSS JOIN:
SELECT *
FROM (SELECT COUNT(id) totalNumOfCustomers
FROM customers
WHERE customers.isDemo =0
AND customers.isLead=0
AND regTime < '2012-01-01'
) t1 CROSS JOIN
(SELECT COUNT(id) as totalNumOfCustomersPerMonth
FROM customers
WHERE customers.isDemo =0
AND customers.isLead=0
AND regTime >='2012-01-01'
AND regTime < '2012-02-01'
) t2 CROSS JOIN
(SELECT COUNT(positions.id) AS totalPositions,
ROUND(SUM(amount),2) - ROUND(SUM(payout),2) AS grossIncome
FROM positions LEFT JOIN
customers
ON positions.customerId = customers.id
WHERE date >= '2012-01-01'
AND date < '2012-02-01'
AND customers.isDemo=0
AND customers.isLead=0
AND status <> 'canceled'
) t3;
Note: don't use single quotes for column and table aliases. That will lead to confusion. Single quotes should only be used for string and date constants.

SQL Query: Cannot perform aggregate functions on sub queries

I have the following SQL query
SELECT
[Date],
DATENAME(dw,[Date]) AS Day,
SUM(CASE WHEN ChargeCode IN (SELECT ChargeCode FROM tblChargeCodes WHERE Chargeable = 1) THEN Units ELSE 0 END) ChargeableTotal,
SUM(CASE WHEN ChargeCode IN (SELECT ChargeCode FROM tblChargeCodes WHERE Chargeable = 0) THEN Units ELSE 0 END) NotChargeableTotal,
SUM(Units) AS TotalUnits
FROM
tblTimesheetEntries
WHERE
UserID = 'PJW'
AND Date >= '2013-01-01'
GROUP BY
[Date]
ORDER BY
[Date] DESC;
But I get the error message:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
Because I am using sub queries in the Case Else Summation.
How can I revise my query to get 2 x Sums of [Units] one for Chargeable = true, and one for Chargeable = false, even though the Chargeable field is in a different table to all the other information. The two tables are linked by ChargeCode which appears in both tblTimesheetEntries and tblChargeCodes.
Have you tried joining the tables on the chargeCode:
SELECT e.[Date],
DATENAME(dw,e.[Date]) AS Day,
SUM(CASE WHEN c.Chargeable = 1 THEN e.Units ELSE 0 END) ChargeableTotal,
SUM(CASE WHEN c.Chargeable = 0 THEN e.Units ELSE 0 END) NotChargeableTotal,
SUM(e.Units) AS TotalUnits
FROM tblTimesheetEntries e
LEFT JOIN tblChargeCodes c
on e.ChargeCode = c.ChargeCode
WHERE e.UserID = 'PJW'
AND e.Date >= '2013-01-01'
GROUP BY e.[Date]
ORDER BY e.[Date] DESC;