SQL concat few select into one big table - sql

I have table with data:
YYYY/MM/DD HH:MM:SS - Number of views, number of clicks, etc..
YYYY/MM/DD HH:MM:SS - ...
I want sum all those columns into sum value.
Like:
1. YYYY/MM/DD - sum of views, sum of clicks
What I have done:
1. Query foreach column.
For views;
select
cast([EventTime] as date) as 'Date',
Count([Id]) as 'Views'
from [TelemetryData]
where [DiscountId] = '8773fd1b-f0c0-41fd-b0a0-ab8238f227f5'
and [EventName] = 'DiscountView'
group by cast([EventTime] as date)
order by cast([EventTime] as date) asc
Number of clicks per day:
select
cast([EventTime] as date) as 'Date',
Count([Id]) as 'Clicks'
from [TelemetryData]
where [DiscountId] = '8773fd1b-f0c0-41fd-b0a0-ab8238f227f5'
and [EventName] = 'DiscountClick'
group by cast([EventTime] as date)
order by cast([EventTime] as date) asc
How I can sum all of them into one row per day?

Try it with checks and sums:
SELECT cast([EventTime] as date) as 'Date', SUM(case when [EventName]='DiscountClick' then 1 else 0 end) as 'Clicks', SUM(case when [EventName]='DiscountView' then 1 else 0 end) as 'Views'
from [TelemetryData]
where [DiscountId] = '8773fd1b-f0c0-41fd-b0a0-ab8238f227f5'
and ([EventName] = 'DiscountView' or [EventName] = 'DiscountClick')
group by cast([EventTime] as date)
order by cast([EventTime] as date) asc
What has been changed:
We first were maded where column to filter both Views and Clicks.
Then we used SUM but with CASE when EVENT=SOMETHING we are adding 1, otherwise 0.
With your group, you will get both by days at one query.

use SUM with CASE..
sum(case when [DiscountId] = '8773fd1b-f0c0-41fd-b0a0-ab8238f227f5'
and [EventName] = 'DiscountClick' then noofclicks column else 0 end
) as clicks
sum(case when [DiscountId] = '8773fd1b-f0c0-41fd-b0a0-ab8238f227f5'
and [EventName] = 'DiscountView' then view column else 0 end
) as views
and so on for other ....
from
table
group by cast([EventTime] as date)
order by cast([EventTime] as date)

Related

CASE WHEN condition with MAX() function

There are a lot questions on CASE WHEN topic, but the closest my question is related to this How to use CASE WHEN condition with MAX() function query which has not been resolved.
Here is some of my sample data:
date
debet
2022-07-15
57190.33
2022-07-14
815616516.00
2022-07-15
40866.67
2022-07-14
1221510.00
So, I want to all records for the last two dates and three additional columns: sum(sales) for the previous day, sum for the current day and the difference between them:
SELECT
[debet],
[date] ,
SUM( CASE WHEN [date] = MAX(date) THEN [debet] ELSE 0 END ) AS sum_act,
SUM( CASE WHEN [date] = MAX(date) - 1 THEN [debet] ELSE 0 END ) AS sum_prev ,
(
SUM( CASE WHEN [date] = MAX(date) THEN [debet] ELSE 0 END )
-
SUM( CASE WHEN [date] = MAX(date) - 1 THEN [debet] ELSE 0 END )
) AS diff
FROM
Table
WHERE
[date] = ( SELECT MAX(date) FROM Table WHERE date < ( SELECT MAX(date) FROM Table) )
OR
[date] = ( SELECT MAX(date) FROM Table WHERE date = ( SELECT MAX(date) FROM Table ) )
GROUP BY
[date],
[debet]
Further, of course, it informs that I can't use the aggregate function inside CASE WHEN. Now I use this combination: sum(CASE WHEN [date] = dateadd(dd,-3,cast(getdate() as date)) THEN [debet] ELSE 0 END). But here every time I need to make an adjustment for weekends and holidays. The question is, is there any other way than using 'getdate' in 'case when' Statement to get max date?
Expected result:
date
sum_act
sum_prev
diff
2022-07-15
97190.33
0.00
97190.33
2022-07-14
0.00
508769.96
-508769.96
You can use dense_rank() to filter the last 2 dates in your table. After that you can use either conditional case expression with sum() to calculate the required value
select [date],
sum_act = sum(case when rn = 1 then [debet] else 0 end),
sum_prev = sum(case when rn = 2 then [debet] else 0 end),
diff = sum(case when rn = 1 then [debet] else 0 end)
- sum(case when rn = 2 then [debet] else 0 end)
from
(
select *, rn = dense_rank() over (order by [date] desc)
from tbl
) t
where rn <= 2
group by [date]
db<>fiddle demo
Two steps:
Get the sums for the last three dates
Show the results for the last two dates.
Well, we could also get all daily sums in step 1, but we just need the last three in order to calculate the sums for the last two days, so why aggregate more data than necessary?
Here is the query. You may have to put the date column name in brackets in SQL Server, as date is a keyword in SQL.
select top(2)
date,
sum_debit_current,
sum_debit_previous,
sum_debit_current - sum_debit_previous as diff
(
select
date,
sum(debet) as sum_debit_current,
lag(sum(debet)) over (order by date) as sum_debit_previous
from table
where date in (select distinct top(3) date from table order by date desc)
group by date
)
order by date desc;
(SQL Server uses TOP(n) instead of standard SQL FETCH FIRST 3 ROWS and while SELECT DISTINCT TOP(3) date looks like "get the top 3 rows, then apply distinct on their date", it is really "apply distinct on the dates, then get the top 3" like in standard SQL.)

MSSQL Group by and Select rows from grouping

I'm trying to figure out if what I'm trying to do is possible. Instead of resorting to multiple queries on a table, I wanted to group the records by business date and id then group by the id and select one date for a field and another date for the other field.
SELECT
*
{AMOUNT FROM DATE}
{AMOUNT FROM OTHER DATE}
FROM (
SELECT
date,
id,
SUM(amount) AS amount
FROM
table
GROUP BY id, date
AS subquery
GROUP BY id
It seems that you're looking to do a pivot query. I usually use cross tabs for this. Based on the query you posted, it could look like:
SELECT
id,
SUM(CASE WHEN date = '20190901' THEN amount ELSE 0 END) AmountFromSept01,
SUM(CASE WHEN date = '20191001' THEN amount ELSE 0 END) AmountFromOct01
FROM (
SELECT
date,
id,
SUM(amount) AS amount
FROM
table
GROUP BY id, date
)AS subquery
GROUP BY id;
You could also use a CTE.
WITH CTE AS(
SELECT
date,
id,
SUM(amount) AS amount
FROM
table
GROUP BY id, date
)
SELECT
id,
SUM(CASE WHEN date = '20190901' THEN amount ELSE 0 END) AmountFromSept01,
SUM(CASE WHEN date = '20191001' THEN amount ELSE 0 END) AmountFromOct01
FROM CTE
GROUP BY id;
Or even be a rebel and do the operation directly.
SELECT
id,
SUM(CASE WHEN date = '20190901' THEN amount ELSE 0 END) AmountFromSept01,
SUM(CASE WHEN date = '20191001' THEN amount ELSE 0 END) AmountFromOct01
FROM CTE
GROUP BY id;
However, some people have tested for performance and found that pre-aggregating can improve performance.
If I understand you correctly, then you're just trying to pivot, but only with two particular dates:
select id,
date1 = sum(iif(date = '2000-01-01', amount, null)),
date2 = sum(iif(date = '2000-01-02', amount, null))
from [table]
group by id

sql join and group by generated date range

I have Table1 and I need a query to populate Table2:
Problem here is with Date column. I want to know the process of location/partner combination per day. Main issue here is that I can't pick DateCreated and make it as default date since it doesn't necessarily cover whole date range, like in this example where it doesn't have 2015-01-07 and 2015-01-09. Same case with other dates.
So, my idea is to first select dates from some table which contains needed date range and then perform calculation for each day/location/partner combination from cte but in that case I can't figure out how to make a join for LocationId and PartnerId.
Columns:
Date - CreatedItems - number of created items where Table1.DateCreated = Table2.Date
DeliveredItems - number of delivered items where Table1.DateDateOut = Table2.Date
CycleTime - number of days delivered item was in the location (DateOut - DateIn + 1)
I started with something like this but it's very like that I completely missed the point with it:
with d as
(
select date from DimDate
where date between DATEADD(DAY, -365, getdate()) and getdate()
),
cr as -- created items
(
select
DateCreated,
LocationId,
PartnerId,
CreatedItems = count(*)
from Table1
where DateCreated is not null
group by DateCreated,
LocationId,
PartnerId
),
del as -- delivered items
(
select
DateOut,
LocationId,
ParnerId,
DeliveredItems = count(*),
CycleTime = DATEDIFF(Day, DateOut, DateIn)
from Table1
where DateOut is not null
and Datein is not null
group by DateOut,
LocationId,
PartnerId
)
select
d.Date
from d
LEFT OUTER JOIN cr on cr.DateCreated = d.Date -- MISSING JOIN PER LocationId and PartnerId
LEFT OUTER JOIN del on del.DateCompleted = d.Date -- MISSING JOIN PER LocationId and PartnerId
with range(days) as (
select 0 union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all
select 6 /* extend as necessary */
)
select dateadd(day, r.days, t.DateCreated) as "Date", locationId, PartnerId,
sum(
case
when dateadd(day, r.days, t.DateCreated) = t.DateCreated
then 1 else 0
end) as CreatedItems,
sum(
case
when dateadd(day, r.days, t.DateCreated) = t.Dateout
then 1 else 0
end) as DeliveredItems,
sum(
case
when dateadd(day, r.days, t.DateCreated) = t.Dateout
then datediff(days, t.DateIn, t.DateOut) + 1 else 0
end) as CycleTime
from
<yourtable> as t
inner join range as r
on r.days between 0 and datediff(day, t.DateCreated, t.DateOut)
group by dateadd(day, r.days, t.DateCreated), LocationId, PartnerId;
If you only want the end dates (rather than all the dates in between) this is probably a better approach:
with range(dt) as (
select distinct DateCreated from T union
select distinct DateOut from T
)
select r.dt as "Date", locationId, PartnerId,
sum(
case
when r.dt = t.DateCreated
then 1 else 0
end) as CreatedItems,
sum(
case
when r.dt = t.Dateout
then 1 else 0
end) as DeliveredItems,
sum(
case
when r.dt = t.Dateout
then datediff(days, t.DateIn, t.DateOut) + 1 else 0
end) as CycleTime
from
<yourtable> as t
inner join range as r
on r.dt in (t.DateCreated, t.DateOut)
group by r.dt, LocationId, PartnerId;
If to specify WHERE clause? Something Like that:
WHERE cr.LocationId = del.LocationId AND
cr.PartnerId = del.PartnerId

sqlite select: grouping in one line, 12 entries

I have a table with fields:
Client_ID, Date, Value
where there is an entry for each of the 12 months of a year (i.e., 12 entries for each client).
I would like to create a table with just one row per Client_ID that contains all the values from each months. Something like:
Client_ID, Date_January, Value_January, Date_February, Value_February, ........, Date_December, Value_December
Can anyone help me with the query?
This is what I'm trying to do (not working...):
select
Client_Id,
case when ((strftime('%m', Date) = '01')) then
Date as Date_January,
Value as Value_January,
else null end
case when ((strftime('%m', Date) = '01')) then
Date as Date_February,
Value as Value_February,
else null end
....
from Test_Table
where
strftime('%Y', Date) = '2013'
;
First you need to untangle your case constructs as they generate a single value. Use:
case
when ((strftime('%m', Date) = '01')) then Date
else null
end as Date_January,
case when ((strftime('%m', Date) = '01')) then Value
else null
end as Value_January,
Then, if you want one row per client, use GROUP BY ClientID.
The third issue is how to aggregate all the Date_January columns into one row. If you really know that there is exactly one row per month per client, you can use MAX() knowing that the not null value will be higher than the NULL values:
select
Client_Id,
MAX(case
when ((strftime('%m', Date) = '01')) then Date
else null
end) as Date_January,
MAX(case when ((strftime('%m', Date) = '01')) then Value
else null
end) as Value_January,
MAX(case
when ((strftime('%m', Date) = '02')) then Date
else null
end) as Date_February,
MAX(case when ((strftime('%m', Date) = '02')) then Value
else null
end) as Value_February,
....
from Test_Table
where
strftime('%Y', Date) = '2013'
group by Client_Id;

SQL Query: Including Two Sums based on different criteria from the same table

I currently have the following sql query
SELECT [Date], DATENAME(dw,[Date]) AS Day, SUM(Units) AS TotalUnits
FROM tblTimesheetEntries
WHERE UserID = 'PJW'
AND Date >= '2013-01-01'
GROUP BY [Date]
ORDER BY [Date] DESC;
Which returns the Total [Units] for a given user and date.
However I would like to produce two separate Total Units based on a new criteria i.e. whether or not the [Units] where 'Chargeable or Not'. There is a field in tblTimeSheets called Chargeable which is a boolean (true for chargeable, false for not). How do I incorporate this to show two Sums one for each type of Units?
You can use a CASE with the SUM() to calculate the separate totals:
SELECT [Date],
DATENAME(dw,[Date]) AS Day,
sum(case when Chargeable = 1 then Units else 0 end) ChargeableTotal,
sum(case when 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;