Related
In a totals row (location is row group, date is the column group), I'm not sure how to calculate a total based on the below expression that I've been using to calculate "overcapacity" daily totals. I'm trying to total up the daily overcap counts.
The below expression works fine when grouped under the "date" column grouping. So each day in the range picked by the user displays with an "overcapacity" count (if the visitscounts > 7, then the result is visitscounts - 7, otherwise it is 0).
But I'm not sure how to total up the resultant overcapacity counts (I can total up visitcounts fine). The issue is that it takes the FULL daily count and THEN applies the -7, instead of just summing all the previously calculated daily counts (if the daily account exceeds 7, then it subtracts 7 from the full daily count, to come up with an "overcapacity" count).
=IIF(SUM(IIF(Fields!Location.Value = "LOC3" OR Fields!Location.Value = "LOC4",Fields!VisitsCount.Value,0)) > 7,
SUM(SUM(IIF(Fields!Location.Value = "LOC3" OR Fields!Location.Value = "LOC4",Fields!VisitsCount.Value,0))-7),
0)
ADDITIONAL INFORMATION
Dataset Query:
SELECT
L.Location
, D.[date]
, COUNT(DISTINCT CAST(V.VisitID AS VARCHAR(10))+V.Location+V.[Room-Bed]) AS VisitsCount
FROM dbo.DateTable(#StartDate, #EndDate) AS D
CROSS JOIN (
SELECT DISTINCT Location FROM dbo.vHIMOverFlowBedReport2)
AS L LEFT JOIN dbo.vHIMOverFlowBedReport2 AS V ON D.[date] BETWEEN
V.EffectiveDate AND ISNULL(V.ServiceEndDate, #EndDate) AND V.Location = L.Location
WHERE V.EffectiveDate IS NULL OR
(V.EffectiveDate <= #EndDate OR
V.ServiceEndDate >= #StartDate OR
V.ServiceEndDate IS NULL)
GROUP BY
L.Location
, D.[date]
ORDER BY L.Location, D.[date]
OverCap New Column Testing
Dataset Query with Added OverCap Column:
SELECT
x.Location
, x.[date]
, x.VisitsCount
, OverCap = IIF(VisitsCount-7 <0 ,0, VisitsCount-7)
FROM (
SELECT
L.Location
, D.[date]
, COUNT(DISTINCT CAST(V.VisitID AS VARCHAR(10))+V.Location+V.[Room-Bed]) AS VisitsCount
FROM dbo.DateTable(#StartDate, #EndDate) AS D
CROSS JOIN (
SELECT DISTINCT Location FROM dbo.vHIMOverFlowBedReport2)
AS L LEFT JOIN dbo.vHIMOverFlowBedReport2 AS V ON D.[date] BETWEEN
V.EffectiveDate AND ISNULL(V.ServiceEndDate, #EndDate) AND V.Location = L.Location
WHERE V.EffectiveDate IS NULL OR
(V.EffectiveDate <= #EndDate OR
V.ServiceEndDate >= #StartDate OR
V.ServiceEndDate IS NULL)
GROUP BY
L.Location
, D.[date]
) x
ORDER BY x.Location, x.[date]
Full Report Layout with OverCap added
Grouped by Location (row) and [date] (column), with a totals row outside row group for combined location.
report layout
Current Resultset with OverCap Column
CurrentResultSet
NOTES:
Result for LOC3-4 is 129 (see CurrentResultSet) if I use:
OverCap = IIF(VisitsCount-7 <0 ,0, VisitsCount-7)
Result for LOC3-4 is 34 if I use:
OverCap = IIF(Location = 'LOC3' OR Location = 'LOC4', VisitsCount,0)
Result for LOC3-4 is 24 if I use:
OverCap = IIF((Location = 'LOC3' OR Location = 'LOC4') AND VisitsCount > 7, VisitsCount,0)
Expressions Used Successfully for GROUPED locations:
DailyVisitorCount (used for both DailyVisitorCount and TotalVisitorCount).
=Sum(Fields!VisitsCount.Value)
DailyOverCapacityCount (used for both DailyOverCapacityCount and TotalOverCapacityCount):
=SWITCH(
Fields!Location.Value = "LOC1" AND Fields!VisitsCount.Value > 24, SUM(Fields!VisitsCount.Value - 24),
Fields!Location.Value = "LOC2" AND Fields!VisitsCount.Value > 16, SUM(Fields!VisitsCount.Value - 16),
Fields!Location.Value = "LOC3" AND Fields!VisitsCount.Value > 7, SUM(Fields!VisitsCount.Value - 7),
Fields!Location.Value = "LOC4" AND Fields!VisitsCount.Value > 7, SUM(Fields!VisitsCount.Value - 7),
Fields!Location.Value = "LOC5" AND Fields!VisitsCount.Value > 11, SUM(Fields!VisitsCount.Value - 11),
True, 0)
Averages were calculated by using the above expressions but adding to the end:
/CountDistinct(Fields!date.Value)
Expressions Used for combined location (outside grouped location row)
DailyVisitorCount (used successfully for both DailyVisitorCount and TotalVisitorCount).
=IIF(Fields!Location.Value = "LOC3" OR Fields!Location.Value = "LOC4", Sum(Fields!VisitsCount.Value), 0)
TotalOverCapCount (used successfully with DAILY TotalOverCapCount, but not the Total TotalOverCapCount
=IIF(SUM(IIF(Fields!Location.Value = "LOC3" OR Fields!Location.Value = "LOC4",Fields!VisitsCount.Value,0)) > 7,
SUM(SUM(IIF(Fields!Location.Value = "LOC3" OR Fields!Location.Value = "LOC4",Fields!VisitsCount.Value,0))-7),
0)
Expressions still needed:
Total TotalOverCapCount (adds up daily totals for the duration)
Average TotalOverCapCount (average of daily totals for the duration)
As the expression you are trying to sum requires two scoped expression parts, it's actually difficult to then sum these.
What you need to do is
=SUM(
SUM(Fields!.MyField.Value, "ColumnGroup")
, "RowGroup")
This is probably not possible in your scenario. I abandoned the approach quickly and just updated the dataset query to return the data I needed instead
So the dataset query looked like this (using you sample data)
DECLARE #t TABLE([Location] varchar(10), [Date] Date, [VisitsCount] int)
INSERT INTO #t VALUES
('LOC1', '2022-10-31', 18), ('LOC1', '2022-11-01', 19),
('LOC1', '2022-11-02', 19), ('LOC2', '2022-10-31', 34),
('LOC2', '2022-11-01', 30), ('LOC2', '2022-11-02', 35),
('LOC3', '2022-10-31', 8), ('LOC3', '2022-11-01', 8),
('LOC3', '2022-11-02', 8), ('LOC4', '2022-10-31', 5),
('LOC4', '2022-11-01', 5), ('LOC4', '2022-11-02', 7),
('LOC5', '2022-10-31', 11), ('LOC5', '2022-11-01', 11),
('LOC5', '2022-11-02', 11)
SELECT
[Location], [Date], VisitsCount
, OverCap = IIF(VisitsCount-7 <0 ,0, VisitsCount-7)
FROM #t
As you can see, I added an OverCap column. Now all we need to do is sum that in the report.
The report design looks like this..
and the final report looks like this...
Obviously you might need to adapt this to suit whatever grouping you have going but I think it's probably a much simpler approach.
Edit after update by OP
You can wrap your original query in a SELECT and then move the order clause of of the sub query. That should give you the same results.
SELECT
[Location], [Date], VisitsCount
, OverCap = IIF(VisitsCount-7 <0 ,0, VisitsCount-7)
FROM (
SELECT
L.Location
, D.[date]
, COUNT(DISTINCT CAST(V.VisitID AS VARCHAR(10))+V.Location+V.[Room-Bed]) AS VisitsCount
FROM dbo.DateTable(#StartDate, #EndDate) AS D
CROSS JOIN (
SELECT DISTINCT Location FROM dbo.vHIMOverFlowBedReport2)
AS L LEFT JOIN dbo.vHIMOverFlowBedReport2 AS V ON D.[date] BETWEEN
V.EffectiveDate AND ISNULL(V.ServiceEndDate, #EndDate) AND V.Location = L.Location
WHERE V.EffectiveDate IS NULL OR
(V.EffectiveDate <= #EndDate OR
V.ServiceEndDate >= #StartDate OR
V.ServiceEndDate IS NULL)
GROUP BY
L.Location
, D.[date]
) x
ORDER BY [Location], [date]
If you want to just get LOC3+4 at the end of the table
Then you can do this in SQL. All I've done here is taken the existing query, dumped the results to a temp table , then returned the results plus an extra row that only contains LOC3 and LOC4 data.
Note: I added a GroupOrder column so you can sort on this in the report to make sure the combined row appears at the end.
SELECT
[Location], [Date], VisitsCount
, OverCap = IIF(VisitsCount-7 <0 ,0, VisitsCount-7)
INTO #t
FROM (
SELECT
L.Location
, D.[date]
, COUNT(DISTINCT CAST(V.VisitID AS VARCHAR(10))+V.Location+V.[Room-Bed]) AS VisitsCount
FROM dbo.DateTable(#StartDate, #EndDate) AS D
CROSS JOIN (
SELECT DISTINCT Location FROM dbo.vHIMOverFlowBedReport2)
AS L LEFT JOIN dbo.vHIMOverFlowBedReport2 AS V ON D.[date] BETWEEN
V.EffectiveDate AND ISNULL(V.ServiceEndDate, #EndDate) AND V.Location = L.Location
WHERE V.EffectiveDate IS NULL OR
(V.EffectiveDate <= #EndDate OR
V.ServiceEndDate >= #StartDate OR
V.ServiceEndDate IS NULL)
GROUP BY
L.Location
, D.[date]
) x
SELECT
GroupOrder = 1
, [Location], [Date], VisitsCount, OverCap
FROM #t
UNION ALL
SELECT
GroupOrder = 2
, [Location] = 'LOC3+4', MIN([Date]), SUM(VisitsCount), SUM(OverCap)
FROM #t
WHERE [Location] IN ('LOC3', 'LOC4')
GROUP BY YEAR([Date]), MONTH([Date])
I am new to sqlite3.I am currently using mysql. But I will be migrating it to sqlite3.
I am calculating month end balance
SELECT c.country,
Date_format(Last_day(Str_to_date(dt.date, '%m/%d/%Y')), '%Y/%m/%d')
AS Month_End_Balance,
Sum(dt.amount) AS in_Euro
FROM deposit_transactions AS dt
LEFT JOIN customers AS c
ON c.customer_id = dt.customer_id
GROUP BY c.country,
Month_End_Balance
order by Month_End_Balance desc
Need help in converting it to sqlite
Question
Need help in Last_Day function alternative in sqlite
Refer below query for SQLITE -
Please make adjustment as per needed date format.
with new_dep_trx as (
select deposit_id,customer_id,
transaction_type,amount,currency,
case when (length(dt.date)=8 or length(dt.date)=9) and instr(substr(dt.date,1,2),'/')>0
then
date(substr(dt.date,length(dt.date)-3,4)||'-0'||substr(dt.date,1,1)||'-0'||substr(dt.date,3,1))
when length(dt.date)=9 and instr(substr(dt.date,1,2),'/')=0
then
date(substr(dt.date,length(dt.date)-3,4)||'-'||substr(dt.date,1,2)||'-0'||substr(dt.date,4,1))
else
date(substr(dt.date,length(dt.date)-3,4)||'-'||substr(dt.date,1,2)||'-'||substr(dt.date,4,2)) end date_col
from deposit_transactions dt
)
select
c.country,
strftime('%Y-%m',dt.date_col) as month,
strftime('%m/%d/%Y',date(dt.date_col,'start of month','+1 month','-1 day')) as last_day_of_month,
strftime('%Y/%m/%d',date(dt.date_col,'start of month','+1 month','-1 day')) as last_day_of_month_your_format,
SUM(
dt.amount *
(CASE WHEN dt.currency = 'GBP' THEN .85 ELSE 1 END) *
(CASE WHEN dt.transaction_type = 'pay_in' THEN 1 ELSE -1 END)
) amount_eur
FROM new_dep_trx dt
LEFT JOIN customers c ON c.customer_id = dt.customer_id
GROUP BY c.country, last_day_of_month_your_format;
Modified DB fiddle.
First, you must update the column date of the table deposit_transactions so that it has the format YYYY-mm-dd the only text date format that you can use with SQLite's datetime functions:
UPDATE deposit_transactions
SET date = SUBSTR(date, -4) || '-' ||
printf('%02d', date + 0) || '-' ||
printf('%02d', SUBSTR(date, INSTR(date, '/') + 1, 2) + 0);
Now, you can use the function date() to get the last day of each month with:
date(date, 'start of month', '+1 month', '-1 day')
So, your query should be:
SELECT c.country,
date(dt.date, 'start of month', '+1 month', '-1 day') AS Month_End_Balance,
SUM(dt.amount *
CASE WHEN dt.currency = 'GBP' THEN .85 ELSE 1 END *
CASE WHEN dt.transaction_type = 'pay_in' THEN 1 ELSE -1 END
) AS amount_eur
FROM deposit_transactions AS dt LEFT JOIN customers AS c
ON c.customer_id = dt.customer_id
GROUP BY c.country, Month_End_Balance
ORDER BY Month_End_Balance DESC;
If you want to format the dates of the resultset to mm/dd/YYYY and sort properly by the date and not the formatted date which would sort incorrectly:
SELECT c.country,
strftime('%m/%d/%Y', date(dt.date, 'start of month', '+1 month', '-1 day')) AS Month_End_Balance,
SUM(dt.amount *
CASE WHEN dt.currency = 'GBP' THEN .85 ELSE 1 END *
CASE WHEN dt.transaction_type = 'pay_in' THEN 1 ELSE -1 END
) AS amount_eur
FROM deposit_transactions AS dt LEFT JOIN customers AS c
ON c.customer_id = dt.customer_id
GROUP BY c.country, date(dt.date, 'start of month', '+1 month', '-1 day')
ORDER BY date(dt.date, 'start of month', '+1 month', '-1 day') DESC;
See the demo.
I want to get the sum of li_units_bought for rows based on li_order_id.
I am joining multiple tables for it. Here is my query:
$query = (new \yii\db\Query())
->select('oid, ord_tracking_no as `Tracking No`, site_name as Region,adv_name as Advertiser, line_id as LineId, li_name as LineName
, li_status as StatusCode, prd_desc as Product, li_version as Version, date_format(lrh_updated_date,"%Y-%m-%d %H:%i") as `Submit Date`
, date_format(li_start_date,"%Y-%m-%d %H:%i") as `Start Date`
, date_format(li_end_date,"%Y-%m-%d %H:%i") as `End Date`, li_is_rush as isRushOrder
, li_type as Type, ord_assigned_user as `Assigned User`, status_desc as Status
, SUM(`li_units_bought`) as Goal
, ldp_total_delivery as `Delivered`
, if(li_type="STANDARD",((ldp_pacing*180)/100)+1,((ldp_pacing+1)*1*180)) as Pacing
, li_cost_type as `Cost Type`
, ord_total_budget as `Total Budget`
, li_is_automated
,li_target_server as Adserver
,li_del_pac_indicator as `DFP Report`
,li_submit_by
' )
->from('lineitems')
->innerJoin('orders','oid = li_order_id')
->leftJoin('advertisers','adv_id=ord_adv_id')
->leftJoin('sites','site_id=ord_site_id')
->leftJoin('products','prd_id=li_product')
->leftJoin('status_ref','status_id=li_status')
->leftJoin('users',"user_id='".$userid."'")
->leftJoin('user_role_profiles','urp_id=user_primary_role')
->leftJoin('lineitem_delivery_pacing','ldp_line_id = line_id')
->innerJoin("user_site_assoc","usc_site_id=ord_site_id and usc_userid='".$_SESSION['userId']."'")
->innerJoin("lineitem_revision_history", "lrh_lineitemid = line_id")
->where(" li_status not in ('Z','X') $cond")
->andWhere("li_order_id = oid")
->groupBy('line_id');
I am getting only the li_units_bought for one row. Not the sum of the rows having the same li_order_id.
Can someone tell me what I'm doing wrong?
I'm running a query that pulls the correct information I'm looking for, but I need it to pull the last 2 business days rather than the last 2 days. This comes into play when it's Monday and my results show information for Monday and Sunday rather than Monday and Friday. How can I change my query to pull in business days only?
USE [LetterGeneration]
SELECT g.LetterGenerationPrintJobId
,CAST(t.[TemplateKey] AS VarChar) AS LetterCode
,convert(char(12),r.CreatedDate,101) AS CreatedDate
,s.LetterGenerationStatusId AS Status
,s.StatusKey AS StatusDesc
,count(g.LetterGenerationId) as LetterCount
,c.BankingDateYorN
FROM [LetterGenerationTemplateRequest] AS r
INNER JOIN [LetterGenerationTemplate] AS t
ON t.[LetterGenerationTemplateId] = r.LetterGenerationTemplateId
INNER JOIN LetterGeneration g
ON g.LetterGenerationTemplateRequestId = r.LetterGenerationTemplateRequestId
INNER JOIN LetterGenerationStatus s
ON g.LetterGenerationStatusId = s.LetterGenerationStatusId
INNER JOIN Enterprise..Calendar C
ON c.BeginDate = g.LetterDate
WHERE ((DATEDIFF(d, r.CreatedDate, GETDATE()) = 0) OR (DATEDIFF(d, r.CreatedDate, GETDATE()) = 1))
--BankingDateYorN = 1
--AND RelativeTimeValue_BusinessDates =-1
AND t.[TemplateKey] NOT LIKE '%PLTV1%'
AND s.LetterGenerationStatusId NOT LIKE '4'
AND s.LetterGenerationStatusId NOT LIKE '16'
AND s.LetterGenerationStatusId NOT LIKE '19'
AND s.LetterGenerationStatusId NOT LIKE '20'
AND s.LetterGenerationStatusId NOT LIKE '38'
GROUP BY r.[LetterGenerationTemplateRequestId]
,r.LetterGenerationTemplateId
,g.Lettergenerationprintjobid
,t.[TemplateKey]
,r.[Loan_no]
,r.CreatedDate
,r.[CreatedBy]
,s.LetterGenerationStatusId
,s.StatusKey
,c.BankingDateYorN
ORDER BY r.CreatedDate DESC
UPDATE: I've recently discovered how to join a calendar table to my current query. The calendar query has a column called BusinessDayYorN with 1's for a business day and 0's for weekends and holidays. I've also updated the old query to now include the join.
select *
from LetterGenerationTemplateRequest
where createddate >= (
getdate() -
case datename(dw,getdate())
when 'Tuesday' then 5
when 'Monday' then 4
else 3
end
)
--and datename(dw,createdDate) not in ('Saturday','Sunday',datename(dw,getdate()))
and datename(dw,createdDate) not in ('Saturday','Sunday')
;
Assuming that you always want to include the last two non-weekend days you can try this:
; with aux as (
select diff = case
when datename(weekday, getdate()) in ('Tuesday', 'Wednesday ', 'Thursday', 'Friday') then 1
else
case datename(weekday, getdate())
when 'Saturday' then 2
when 'Sunday' then 3
when 'Monday' then 4
end
end
)
SELECT --r.[LetterGenerationTemplateRequestId]
--,r.LetterGenerationTemplateId
g.LetterGenerationPrintJobId
,CAST(t.[TemplateKey] AS VarChar) AS LetterCode
,r.[Loan_no]
,convert(char(12),r.CreatedDate,101) AS CreatedDate
-- ,g.ModifiedDate
-- ,convert(varchar(18), g.ModifiedDate - r.CreatedDate, 108) AS TimeSpan
,s.LetterGenerationStatusId AS Status
,s.StatusKey AS StatusDesc
,count(g.LetterGenerationId) as LetterCount
FROM [LetterGenerationTemplateRequest] AS r
INNER JOIN [LetterGenerationTemplate] AS t
ON t.[LetterGenerationTemplateId] = r.LetterGenerationTemplateId
INNER JOIN LetterGeneration g
ON g.LetterGenerationTemplateRequestId = r.LetterGenerationTemplateRequestId
INNER JOIN LetterGenerationStatus s
ON g.LetterGenerationStatusId = s.LetterGenerationStatusId
WHERE
DATEDIFF(day, r.CreatedDate, GETDATE()) <= (select diff from aux)
AND t.[TemplateKey] NOT LIKE '%PLTV1%'
AND s.LetterGenerationStatusId NOT LIKE '4'
AND s.LetterGenerationStatusId NOT LIKE '16'
AND s.LetterGenerationStatusId NOT LIKE '19'
AND s.LetterGenerationStatusId NOT LIKE '20'
AND s.LetterGenerationStatusId NOT LIKE '38'
GROUP BY r.[LetterGenerationTemplateRequestId]
,r.LetterGenerationTemplateId
,g.Lettergenerationprintjobid
,t.[TemplateKey]
,r.[Loan_no]
,r.CreatedDate
-- ,g.ModifiedDate
,r.[CreatedBy]
,s.LetterGenerationStatusId
,s.StatusKey
ORDER BY r.CreatedDate DESC
The CTE aux returns a dataset with only one record and only one field, the value of which is the number of days you need to go back in your WHERE statement.
I have a complicated query that returns a percentage but I need to have it return only 2 decimal places. I have searched the forums and trues truncate, round, cast, decimal, and a few others I am sure I am missing. I am at a complete loss as to where to go from here. The query is below. Any help would be greatly appreciated.
Code
SELECT branch, SUM( monthly_total / (
SELECT SUM(hour1)
FROM `door_count`
WHERE `numeric_month` <= MONTH( CURRENT_DATE( ) )
AND fy = 2013
AND numeric_month <> '0'
AND branch = 'Main St.'
) *100
)
FROM door_count
WHERE fy = 2014
AND branch = 'Main St.';
Use the ROUND() function:
SELECT branch, ROUND(SUM( monthly_total / (
SELECT SUM(hour1)
FROM `door_count`
WHERE `numeric_month` <= MONTH( CURRENT_DATE( ) )
AND fy = 2013
AND numeric_month <> '0'
AND branch = 'Main St.'
) *100
), 2)
FROM door_count
WHERE fy = 2014
AND branch = 'Main St.';