sql combining two queries and truncating date - sql

I am trying to truncate dates to only get year/month as opposed to the form they are in which is year/month/day.time
What I want to do is count all of the cars that sold each month and all of the suvs that sold each month, having something like:
// counts cars
select SellDate, count(*)
from category
where machineIdentification = 1
GROUP BY SellDate
// counts suv's
select SellDate, count(*)
from category
where machineIdentification = 2
GROUP BY SellDate
Separately running each query gives me a list of dates (y/m/d/time to the second) and the number 1 because only 1 car or suv sold that exact time, however I am trying to group by SellDate and truncate the date so it only shows me the total numbers each month.
what I am trying to do is combine the queries and end up with values like so:
2009-01 23 10
2009-02 13 14
2009-03 29 7
With the first column being the year.month, the second being # of cars sold and the third being # of suv's sold

select
date(SellDate, 'start of month'),
SUM (CASE machineIdentification = 1 THEN 1 ELSE 0 END) AS carcount ,
SUM (CASE machineIdentification = 2 THEN 1 ELSE 0 END) AS suvcount
from category
where machineIdentification IN (1, 2 )
GROUP BY date(SellDate, 'start of month')
I'd concatenate the year/month in the client code so you can have "July 2010" for example
(I can't test in SQLLite, sorry, but this should be close except for output year/month format)

It could involve a union in a subquery and a format on the date, reformatted for SQLLite:
SELECT SellDate, COUNT(CARS) AS Cars, COUNT(SUVS) AS SUVS
FROM
(SELECT STRFTIME('%Y-%m',SellDate) AS SellDate,
MachineIdentification AS CARS, null AS SUVS
FROM Category
where machineIdentification = 1
UNION
SELECT STRFTIME('%Y-%m',SellDate) AS SellDate,
null AS CARS, MachineIdentification AS SUVS
FROM Category
where machineIdentification = 2
)
GROUP BY SellDate

Related

Combine different results of "group by" queries in the same table

I need to make some comparation between 2 years: sales by product, sales by category, etc.
How can I have this in one table having 3 columns:
first column = product, category, etc
second column = sales in 2021
third column = sales in 2022
Sample of queries that must be combined in one single table as the one below
select product_code, sum(amount)
from product
where year = '2021'
group by product_code
select product_code, sum(amount)
from product
where year = '2022'
group by product_code
select category_code, sum(amount)
from category
where year = '2021'
group by category_code
select category_code, sum(amount)
from category
where year = '2022'
group by category_code
Please, see the final table
[1]: https://i.stack.imgur.com/smF7h.png
NOTE!
If for instance in 2021 there was no "product D", it will be 0 for "Sales_2021" or the "product A" is no longer present in 2022, it will be 0 for "Sales_2022".
Thank you
You need two things here:
Conditional aggregation (a CASE expression inside the aggregation function) in order to get 2021 and 2022 in one go.
A union of two intermediate result sets (product figures UNION ALL category figures).
And as any table - and a query result is again a table - is unordered, we need an ORDER BY at last to get products first and categories second and also the products ordered alphabetically and the categories, too.
The complete query:
select category_or_product, sales_2021, sales_2022
from
(
select
product_code as category_or_product,
sum(case when year = 2021 then amount else 0 end) as sales_2021,
sum(case when year = 2021 then amount else 0 end) as sales_2022,
1 as product_first
from product
group by product_code
union all
select
category_code as category_or_product,
sum(case when year = 2021 then amount else 0 end) as sales_2021,
sum(case when year = 2021 then amount else 0 end) as sales_2022,
2 as product_first
from category
group by category_code
) unioned
order by product_first, category_or_product;

How to Count the number of times of purchases per customer in a Month?

I would like to know how many times a customer bought per month since the store has been opened.
I have this code:
SELECT
Descrip Customer_Name
, CodClie ID_Customer
, CASE WHEN TipoFac = 'A' THEN Monto
ELSE -Monto END AS Purchase_Amount$
, CONVERT(varchar, FechaE, 1) AS Date
, CodUbic Store_Location
, DENSE_RANK() OVER ( partition by Descrip order by NumeroD) +
DENSE_RANK() OVER (partition by Descrip order by NumeroD desc) -1 as Times_bought_since_1st_Day
FROM
dbo.SAFACT
WHERE
TipoFac IN ('A', 'B')
GROUP BY
FechaE --- Date in timestamp, that's why I converted it
, CodUbic --- Stores Location
, Monto --- Amount spent $
, Descrip --- Customer Name
, TipoFac --- A for purchases, B for returned products, that why I make the Case Statement
, CodClie --- ID Customer
, NumeroD --- NumeroD = Bill
ORDER BY YEAR(FechaE) DESC, MONTH(FechaE) DESC, DAY(FechaE) DESC;
If I run this code, It will show something like this:
Customer_Name ID_Customer Purchase_Amount$ Date Store_Location Times_bought_since_1st_Day
------------------------------------------------------------------------------------------------
Peter Grifin 12345678 1.5 06/14/2022 000-1 10
Ralph Lauren 89101112 2.0 06/14/2022 000-4 15
Meg Stacy 13141516 4.0 06/14/2022 000-5 10
The issue here is that I need the times bought but per month, even if It is possible make a group by per every customer's name and their amount spent together with the times bought
The expected result would be something like:
Customer_Name ID_Customer Purchase_Amount$ Date StoreLocation TimesBoughtSince1stDay TimesBoughtCurrentMonth TotalSpentSince1stDay TotalSpentThisMonth
------------------------------------------------------------------------------------------------------------------------------------------------------------
Peter Grifin 12345678 1.5 06/14/2022 000-1 10 20 100.000 1.000
Ralph Lauren 89101112 2.0 06/14/2022 000-4 15 05 25.000 500.00
Meg Stacy 13141516 4.0 06/14/2022 000-5 18 10 15.000 200.00
If there any possibility to split the times bought per month?
I think that you are confusing because you want to mix calculations within differents times aggregations in one table from the beggining. If you think the problem like 3 different problems and then mixing them, it will be easier.
Try to calculate in different tables by time aggregation and then joining the tables.
The first 5 columns of what you want to achieve are transactional data with an aggregation of days. Every row is a sale made one specific day, a customer can do 1 or more purchases every day.
Then, with the columns TimesBoughtSince1stDay and TotalSpentSince1stDay you don´t need to aggregate by date. You need to aggregate by Customer entire history and you can achieve that by doing:
SELECT
Descrip Customer_Name
,CodClie ID_Customer
,sum(CASE WHEN TipoFac = 'A' THEN Monto ELSE -Monto END) 'Purchase_Amount$'
, count( DISTINCT NumeroD ) -- here I don´t understand that much your code but you need to count differents SaleId's
FROM dbo.SAFACT
WHERE TipoFac IN ('A', 'B')
GROUP BY Descrip Customer_Name, CodClie ID_Customer
For the month time aggregation you can do someting like:
SELECT
Descrip Customer_Name
, CodClie ID_Customer
, sum(CASE WHEN TipoFac = 'A' THEN Monto
ELSE -Monto END) 'Purchase_Amount$'
, count( DISTINCT NumeroD ) -- here I don´t understand that much your code but you need to count differents SaleId's
FROM
dbo.SAFACT
WHERE
TipoFac IN ('A', 'B')
AND MONTH(CONVERT(DATE,FechaE)) = MONTH(GETDATE())
AND YEAR(CONVERT(DATE,FechaE)) = YEAR(GETDATE())
GROUP BY Descrip Customer_Name, CodClie ID_Customer, MONTH(CONVERT(DATE,FechaE))
Once you have your 3 differents tables(aggregation by date, aggregation by customer history and aggregation by month) you need to do a left join over the "aggregation by date" table.
Surely some of the code isn´t 100% ready to run but i wanted you to catch the main idea. Hope it will help!

SQL - Calculate the difference in number of orders by month

I am working on the orders table provided by this site, it has its own editor where you can test your SQL statements.
The order table looks like this
order_id
customer_id
order_date
1
7000
2016/04/18
2
5000
2016/04/18
3
8000
2016/04/19
4
4000
2016/04/20
5
NULL
2016/05/01
I want to get the difference in the number of orders for subsequent months.
To elaborate, the number of orders each month would be like this
SQL Statement
SELECT
MONTH(order_date) AS Month,
COUNT(MONTH(order_date)) AS Total_Orders
FROM
orders
GROUP BY
MONTH(order_date)
Result:
Month
Total_Orders
4
4
5
1
Now my goal is to get the difference in subsequent months which would be
Month
Total_Orders
Total_Orders_Diff
4
4
4 - Null = Null
5
1
1 - 4 = -3
My strategy was to self-join following this answer
This was my attempt
SELECT
MONTH(a.order_date),
COUNT(MONTH(a.order_date)),
COUNT(MONTH(b.order_date)) - COUNT(MONTH(a.order_date)) AS prev,
MONTH(b.order_date)
FROM
orders a
LEFT JOIN
orders b ON MONTH(a.order_date) = MONTH(b.order_date) - 1
GROUP BY
MONTH(a.order_date)
However, the result was just zeros (as shown below) which suggests that I am just subtracting from the same value rather than from the previous month (or subtracting from a null value)
MONTH(a.order_date)
COUNT(MONTH(a.order_date))
prev
MONTH(b.order_date)
4
4
0
NULL
5
1
0
NULL
Do you have any suggestions as to what I am doing wrong?
You have to use LAG window function in your SELECT statement.
LAG provides access to a row at a given physical offset that comes
before the current row.
So, this is what you need:
SELECT
MONTH(order_date) as Month,
COUNT(MONTH(order_date)) as Total_Orders,
COUNT(MONTH(order_date)) - (LAG (COUNT(MONTH(order_date))) OVER (ORDER BY (SELECT NULL))) AS Total_Orders_Diff
FROM orders
GROUP BY MONTH(order_date);
Here in an example on the SQL Fiddle: http://sqlfiddle.com/#!18/5ed75/1
Solution without using LAG window function:
WITH InitCTE AS
(
SELECT MONTH(order_date) AS Month,
COUNT(MONTH(order_date)) AS Total_Orders
FROM orders
GROUP BY MONTH(order_date)
)
SELECT InitCTE.Month, InitCTE.Total_Orders, R.Total_Orders_Diff
FROM InitCTE
OUTER APPLY (SELECT TOP 1 InitCTE.Total_Orders - CompareCTE.Total_Orders AS Total_Orders_Diff
FROM InitCTE AS CompareCTE
WHERE CompareCTE.Month < InitCTE.Month) R;
Something like the following should give you what you want - disclaimer, untested!
select *, Total_Orders - lag(Total_orders,1) over(order by Month) as Total_Orders_Diff
from (
select Month(order_date) as Month, Count(*) as Total_Orders
From orders
Group by Month(order_date)
)o

Datediff on 2 rows of a table with a condition

My data looks like the following
TicketID OwnedbyTeamT Createddate ClosedDate
1234 A
1234 A 01/01/2019 01/05/2019
1234 A 10/05/2018 10/07/2018
1234 B 10/04/2019 10/08/2018
1234 finance 11/01/2018 11/11/2018
1234 B 12/02/2018
Now, I want to calculate the datediff between the closeddates for teams A, and B, if the max closeddate for team A is greater than max closeddate team B. If it is smaller or null I don't want to see them. So, for example,I want to see only one record like this :
TicketID (Datediff)result-days
1234 86
and for another tickets, display the info. For example, if the conditions aren't met then:
TicketID (Datediff)result-days
2456 -1111111
Data sample for 2456:
TicketID OwnedbyTeamT Createddate ClosedDate
2456 A
2456 A 10/01/2019 10/05/2019
2456 B 08/05/2018 08/07/2018
2456 B 06/04/2019 06/08/2018
2456 finance 11/01/2018 11/11/2018
2456 B 12/02/2018
I want to see the difference in days between 01/05/2019 for team A, and
10/08/2018 for team B.
Here is the query that I wrote, however, all I see is -1111111, any help please?:
SELECT A.incidentid,
( CASE
WHEN Max(B.[build validation]) <> 'No data'
AND Max(A.crfs) <> 'No data'
AND Max(B.[build validation]) < Max(A.crfs) THEN
Datediff(day, Max(B.[build validation]), Max(A.crfs))
ELSE -1111111
END ) AS 'Days-CRF-diff'
FROM (SELECT DISTINCT incidentid,
Iif(( ownedbyteam = 'B'
AND titlet LIKE '%Build validation%' ), Cast(
closeddatetimet AS NVARCHAR(255)), 'No data') AS
'Build Validation'
FROM incidentticketspecifics) B
INNER JOIN (SELECT incidentid,
Iif(( ownedbyteamt = 'B'
OR ownedbyteamt =
'Finance' ),
Cast(
closeddatetimet AS NVARCHAR(255)), 'No data') AS
'CRFS'
FROM incidentticketspecifics
GROUP BY incidentid,
ownedbyteamt,
closeddatetimet) CRF
ON A.incidentid = B.incidentid
GROUP BY A.incidentid
I hope the following answer will be of help.
With two subqueries for the two teams (A and B), the max date for every Ticket is brought. A left join between these two tables is performed to have these information in the same row in order to perform DATEDIFF. The last WHERE clause keeps the row with the dates greater for A team than team B.
Please change [YourDB] and [MytableName] in the following code with your names.
--Select the items to be viewed in the final view along with the difference in days
SELECT A.[TicketID],A.[OwnedbyTeamT], A.[Max_DateA],B.[OwnedbyTeamT], B.[Max_DateB], DATEDIFF(dd,B.[Max_DateB],A.[Max_DateA]) AS My_Diff
FROM
(
--The following subquery creates a table A with the max date for every project for team A
SELECT [TicketID]
,[OwnedbyTeamT]
,MAX([ClosedDate]) AS Max_DateA
FROM [YourDB].[dbo].[MytableName]
GROUP BY [TicketID],[OwnedbyTeamT]
HAVING [OwnedbyTeamT]='A')A
--A join between view A and B to bring the max dates for every project
LEFT JOIN (
--The max date for every project for team B
SELECT [TicketID]
,[OwnedbyTeamT]
,MAX([ClosedDate]) AS Max_DateB
FROM [YourDB].[dbo].[MytableName]
GROUP BY [TicketID],[OwnedbyTeamT]
HAVING [OwnedbyTeamT]='B')B
ON A.[TicketID]=B.[TicketID]
--Fill out the rows on the max dates for the teams
WHERE A.Max_DateA>B.Max_DateB
You might be able to do with a PIVOT. I am leaving a working example.
SELECT [TicketID], "A", "B", DATEDIFF(dd,"B","A") AS My_Date_Diff
FROM
(
SELECT [TicketID],[OwnedbyTeamT],MAX([ClosedDate]) AS My_Max
FROM [YourDB].[dbo].[MytableName]
GROUP BY [TicketID],[OwnedbyTeamT]
)Temp
PIVOT
(
MAX(My_Max)
FOR Temp.[OwnedbyTeamT] in ("A","B")
)PIV
WHERE "A">"B"
Your sample query is quite complicated and has conditions not mentioned in the text. It doesn't really help.
I want to calculate the datediff between the closeddates for teams A, and B, if the max closeddate for team A is greater than max closeddate team B. If it is smaller or null I don't want to see them.
I think you want this per TicketId. You can do this using conditional aggregation:
SELECT TicketId,
DATEDIFF(day,
MAX(CASE WHEN OwnedbyTeamT = 'B' THEN ClosedDate END),
MAX(CASE WHEN OwnedbyTeamT = 'A' THEN ClosedDate END) as diff
)
FROM incidentticketspecifics its
GROUP BY TicketId
HAVING MAX(CASE WHEN OwnedbyTeamT = 'A' THEN ClosedDate END) >
MAX(CASE WHEN OwnedbyTeamT = 'B' THEN ClosedDate END)

Bring through a newly created calculated column in another query

I have 2 separate queries below which run correctly.Now I've created a calculated column to provide a count of working days by YMs and would like to bring this through to query1(the join would be query1.Period = query2.Yms)
please see the query and outputs below.
SELECT Client, ClientGroup, Type, Value, Period, PeriodName, PeriodNumber, ClientName
FROM metrics.dbo.vw_KPI_001_Invoice
select YMs,sum(case when IsWorkDay = 'X' then 1 else 0 end) from IESAONLINE.Dbo.DS_Dates
where Year > '2013'
group by YMs
Query 1
Client ClientGroup Type Value Period PeriodName PeriodNumber ClientName
0LG0 KarroFoods Stock 5691.68 201506 Week 06 2015 35 Karro Foods Scunthorpe
Query 2
YMs (No column name)
201401 23
Would the following work:
SELECT Client, ClientGroup, Type, Value, Period, PeriodName, PeriodNumber, ClientName, cnt
FROM metrics.dbo.vw_KPI_001_Invoice q1
INNER JOIN (select YMs,sum(case when IsWorkDay = 'X' then 1 else 0 end) as cnt from IESAONLINE.Dbo.DS_Dates
where Year > '2013'
group by YMs ) q2 ON q1.Period = q2.YMs
If a value isn't always available then you might consider changing the INNER JOIN to an OUTER JOIN.