Join tables and Count participants in the past - sql

I have participants that have multiple orders. I can easily find counts of orders in the past but have to use a join to count participants in the past. The code I am using does not give me correct numbers. The code is :
select count(distinct o.participant_id)
from dbaq.participant p, dbaq.orders o
where o.participant_id=p.participant_id and
(p.water_staff=1) and p.active = '1' and
date_part('year', o.order_date) = 2018;
I figured out why this is not going to work ... the number of active participants goes down when I look at each subsequent year in the past ... becasue they are leaving and no longer active. I don't think there is a way to track who was active in the past. Thanks for your input though - great suggestions below.

I think you want to find the number of participants for an active order in this year. Am I right? If yes you could try
SELECT o.participant_id,
COUNT(*)
FROM dbaq.participant p,
dbaq.orders o
WHERE o.participant_id = p.participant_id
AND p.water_staff = 1
AND p.active = '1'
AND extract(YEAR FROM o.order_date) = '2018'
group by o.participant_id;

Try this:
SELECT
COUNT(DISTINCT o.participant_id)
FROM
dbaq.orders o
JOIN
dbaq.participant p
ON
o.participant_id = p.participant_id
WHERE
p.water_staff = 1
AND
p.active = '1'
AND
DATE_PART('year', o.order_date) = 2018;

Related

daily incremental results on table where transaction date <= #Date parameter

specifically looking for General Leger results. This means that I can't sum up transactions for specfic dates, or cant run Between date.
to get the results for say, today I would need to query the table for all transactions <= #Today.
That said, i am tasked with running this for every single day in 2020 thus far. is there a method to do this where i dont have to manually run for each day myself?
Query example:
glo.GLValue
, Sum(UnitCR) AS 'Credit'
, Sum(UnitDR) AS 'Debit'
, sum(FirmCR) AS 'FirmCredit'
, sum(FirmDR) AS 'FirmDebit'
FROM glacct ga
inner join gldetail gd on gd.glacct = ga.AcctIndex
inner join glnatural gn on ga.glnatural = gn.GLNaturalID
inner join glunit glu on ga.glunit = glu.GLUnitID
inner join gloffice glo on ga.GLOffice = glo.GLOfficeID
WHERE gn.GLNat IN ('11001','11002','11003','11005','11007','11011','11016','11019','11020','11021','11022','11024','11025','11026','11027','11032','11033',
'11034','11035','11036','11037','11040','11041','11042','11043','11044','11050','11051','11052','11053','11190','11199','11201','11202','11203','11204',
'11205','11206','11207','11301','11603','11700','11705','11801','11802','11803','11804','11806','11807','11808','11809','11901')--,'22001')
AND gd.PostDate <= #Yesterday
GROUP BY
glo.GLValue
Create a sub-table that give the sums for each PostDate and GLValue similar to above but also grouped on PostDate, then join that to your select above, e.g.
inner join gloffice glo on ga.GLOffice = glo.GLOfficeID
inner join ( ... new grouped select here ...) gs on gs.GLValue = glo.GlValue and gs.PostDate < gd.PostDate
Now you should be able to sum the gs values:
, Sum(gs.Credit) as Credit
, Sum(gs.Debit) as Debit
etc.

How to use 1 SQL query related to date and time in order to compare value difference

SELECT c.treatment_category, a.treatment_id, MAX(a.counts - b.counts) AS ReviewDifference
FROM
(SELECT treatment_id, COUNT(treatment_id) AS counts
FROM review
WHERE DATE(review.created) BETWEEN DATE(TIMESTAMP'2016-01-01 00:00:00.0') AND DATE(TIMESTAMP'2016-12-31 23:59:59.999')
GROUP BY treatment_id) a
LEFT JOIN
(SELECT treatment_id, COUNT(treatment_id)
FROM review
WHERE DATE(review.created) BETWEEN DATE(TIMESTAMP'2015-01-01 00:00:00.0') AND DATE(TIMESTAMP'2015-12-31 23:59:59.999')
GROUP BY treatment_id) b
ON a = b
LEFT JOIN
(SELECT t.treatment_category AS category, r.treatment_id AS number
FROM treatment t
LEFT JOIN review r
ON t.treatment_id = r.treatment_id
GROUP BY category, number) c
ON b.treatment_id = c.number
GROUP BY a.treatment_id, c.treatment_category
ORDER BY ReviewDifference DESC
LIMIT 1;
I need some hints or simpler query on how to do this question since it is related to date and time. Thank you.
What treatment category has seen the biggest increase in reviews from 2015 to 2016?
Please see below for the tables.
I have provided my code snippet and I would like to find a simpler and cleaner way on writing the code.
SELECT t.treatment_id, t.treatment_name,
COUNT( CASE WHEN YEAR(created) = 2016 THEN r.review_id END)
- COUNT( CASE WHEN YEAR(created) = 2015 THEN r.review_id END) as review_count
FROM treatments t
JOIN reviews r
ON t.treatment_id = r.treatment_id
GROUP BY t.treatment_id, t.treatment_name,
ORDER BY review_count DESC

How to fix "Conversion from string "August" to type 'Date' is not vaid in SSRS

SELECT
a.ItemCode,
SUM(a.NoOfApplication) AS NoOfApplication,
SUM(a.NoOfAccomplished) AS NoOfAccomplished,
SUM(a.NoOfPending) AS NoOfPending,
SUM(a.NoOfDocumentCompliance) AS NoOfDocumentCompliance,
a.[Year]
FROM
(SELECT
ItemCode,
COUNT(am.ReferenceNumber) AS NoOfApplication,
COUNT(TNA.NoOfAccomplished) AS NoOfAccomplished,
COUNT(TNP.NoOfPending) AS NoOfPending,
SUM(FDC.NoOfDocumentCompliance) AS NoOfDocumentCompliance,
DATENAME(month, ad.applicationdate) AS [Year]
FROM
AppTypes at
INNER JOIN
AssessmentMainDetails am ON at.Category = am.Category
INNER JOIN
InspectionProcesses i ON am.ReferenceNumber = i.ReferenceNo
LEFT JOIN
(SELECT
COUNT(Status) AS NoOfDocumentCompliance,
ReferenceNumber, Status
FROM
ApplicationStatus
WHERE
Status = 'For Document Compliance'
GROUP BY
ReferenceNumber, Status) AS FDC ON FDC.ReferenceNumber = i.ReferenceNo
LEFT JOIN
(SELECT
COUNT(ReferenceNo) AS NoOfAccomplished,
ReferenceNo
FROM
InspectionProcesses
WHERE
DateOfInspection <> ''
GROUP BY
ReferenceNo) AS TNA ON TNA.ReferenceNo = i.ReferenceNo
LEFT JOIN
(SELECT
COUNT(ReferenceNo) AS NoOfPending, ReferenceNo
FROM
InspectionProcesses
WHERE
DateOfInspection = ''
GROUP BY
ReferenceNo) AS TNP ON TNP.ReferenceNo = i.ReferenceNo
INNER JOIN
ApplicationDetails ad on i.ReferenceNo = ad.ReferenceNumber
INNER JOIN
Companies c on ad.CompanyId = c.CompanyID
INNER JOIN
Zones z on c.zonecode = z.zonecode
INNER JOIN
ZoneGroups zg on z.ZoneGroup = zg.ZoneGroupId
WHERE
DateOfInspection = ''
AND ad.ApplicationDate BETWEEN '2017-08-01' AND '2017-09-30'
AND zg.ZoneGroupCode = 'HO'
AND z.ZoneCode = 'VIDC'
GROUP BY
ItemCode, DATENAME(month, ad.applicationdate)) a
GROUP BY
a.ItemCode, a.[Year]
This my code, I already converted my date to get the month name. Please I need help
Look carefully. That giant derived table (a - nice meaningful name btw) has the same group by clause as the outermost query. So that means that [a] has a single row per ItemCode and datename(month, ad.applicationdate). Therefore, there is nothing to sum in your outer query since it is grouping by the same columns.
You also have the expression:
DateOfInspection = ''
which is highly suspicious based on the name of the column. What datatype is the DateOfInspection column? Doesn't sound like it should be string-based.
And lastly, the error message you posted sounds like it comes from SSRS and not sql server. Is that the case? Does your query run correctly from SSMS? Then the problem is in your report - and it would seem that you attempt to manipulate or interpret the Year column as a date (perhaps for sorting?). It also seems a bit short-sighted in your report design that your "Year" column is actually the name of a month and that your resultset does not include the year in some fashion. What happens when your data spans more than twelve months? And how do you intend to sort your report when you have month name but not month number?

Show 0 for null rows

I'm working on a comparison query that will compare what was processed for the different credit card types versus what was actually processed by our POS service. I have ran into an issue where I am not seeing rows for certain card types if they did not process any payments on a given day but may have given a refund. IE: Nothing purchased with VISA but a VISA refund was given, but due to no purchases the row does not show up even though there's a refund for that type.
Here is my query:
WITH tran_total AS (
SELECT CONCAT(c.id_str, ' - ', c.clinic_str) AS Clinics,
t.clinic,
c.xcharge_mid,
p.pay_desc,
CAST(t.time_ran AS date) AS tran_date,
CASE WHEN SUM(t.amount) <> 0 THEN SUM(t.amount) * - 1
ELSE 0.00 END AS collection
FROM dbo.transactions AS t INNER JOIN
dbo.clinic_master AS c ON t.clinic = c.clinic INNER JOIN
dbo.paytype AS p ON t.clinic = p.clinic AND t.paytype_id = p.paytype_id
WHERE (t.time_ran > GETDATE() - 10)
AND (t.paytype_id IS NOT NULL)
AND (p.pay_desc = 'Visa' OR
p.pay_desc = 'MasterCard' OR
p.pay_desc = 'American Express' OR
p.pay_desc = 'Discover')
GROUP BY c.id_str, c.clinic_str, t.clinic, c.xcharge_mid, p.pay_desc, CAST(t.time_ran AS date))
SELECT w.Clinics,
w.pay_desc,
w.tran_date,
w.collection,
CASE WHEN w.pay_desc = 'Visa' THEN (SUM(VI_pur) - SUM(VI_ref))
WHEN w.pay_desc = 'MasterCard' THEN (SUM(MC_pur) - SUM(MC_ref))
WHEN w.pay_desc = 'American Express' THEN (SUM(AX_pur) - SUM(AX_ref))
WHEN w.pay_desc = 'Discover' THEN (SUM(DI_pur) - SUM(DI_ref)) END AS xcharge
FROM tran_total AS w LEFT OUTER JOIN
dbo.xcharge AS x ON w.xcharge_mid = x.xcharge_mid AND w.tran_date = x.settle_date
GROUP BY w.Clinics, w.pay_desc, w.tran_date, w.collection
ORDER BY w.Clinics, w.tran_date
I've thought about switching this around and starting with the comparison from the xcharge table but there is not a pay_desc that links those easily and if something is processed as the wrong card (VISA is chosen but Discover is scanned) then I feel the rows would be missed still.
What I would like, is for all of the pay_desc to show up for each tran_date even if the SUM(t.amount) does not have a value. I've tried a case statement to accomplish this without any luck.
EDIT: I feel the issue is more due to the t.time_ran variable. If there isn't a payment for a given pay_desc then there won't be a t.time_ran either, is there a function I can do to list out dates between GETDATE()-10 AND GETDATE() kind of thing and just have the t.time_ran and x.settle_date match up to that variable instead?
Any thoughts on this? Thanks in advance
UPDATE:
I have created a calendar table with individual dates and have tried the following query:
WITH tran_test AS(
SELECT cal.calendardate AS cd,
p.clinic,
p.pay_desc,
p.paytype_id
FROM calendar cal, paytype p
WHERE cal.calendardate BETWEEN GETDATE()-10 AND GETDATE()+1
AND (p.pay_desc = 'Visa' OR
p.pay_desc = 'MasterCard' OR
p.pay_desc = 'American Express' OR
p.pay_desc = 'Discover'))
SELECT w.cd,
CONCAT(c.id_str, ' - ', c.clinic_str) AS Clinics,
w.pay_desc,
ISNULL(SUM(t.amount)*-1, 0) AS collection,
CASE WHEN w.pay_desc = 'Visa' THEN (SUM(x.VI_pur) - SUM(x.VI_ref))
WHEN w.pay_desc = 'MasterCard' THEN (SUM(x.MC_pur) - SUM(x.MC_ref))
WHEN w.pay_desc = 'American Express' THEN (SUM(x.AX_pur) - SUM(x.AX_ref))
WHEN w.pay_desc = 'Discover' THEN (SUM(x.DI_pur) - SUM(x.DI_ref)) END AS xcharge
FROM tran_test w
INNER JOIN clinic_master c
ON (w.clinic=c.clinic)
LEFT OUTER JOIN transactions t
ON (t.clinic=w.clinic AND t.paytype_id=w.paytype_id AND CAST(t.time_ran AS date) = w.cd)
LEFT OUTER JOIN xcharge x
ON (w.cd=x.settle_date AND c.xcharge_mid=x.xcharge_mid)
GROUP BY w.cd, c.id_str, c.clinic_str, w.pay_desc
ORDER BY w.cd
However, I'm not getting an issue where my xcharge column seems to multiplying itself by random intervals and I'm not sure why.
It sounds like what you need is a Calendar table. You can generate one as part of a CTE (many examples on this site or just search Google), but IMO you should have a persistent table in your database. This way you can mark certain days as bank holidays, what quarter your business considers them to be in, etc.
Once you have that table in place you can SELECT your dates from that table and then LEFT OUTER JOIN to that table from your Transactions table. Any dates without matching rows in Transactions will still show up with a row, but you'll have 0.00 value for your SUM.

Convert heavy asp code to run in sql

A bit of asp code which in context does; timeline the product's sales performance based on the start year which product was online to the number of years active, for example a product published on 2000 would have the peak sales for couple of years but by 2004 there would be none...but code this is for all products in the system and grouping by year...(if you questions I can answer them or I think looking at code would give a fair idea on what it's doing !!)
Firstly it runs this query to get the data ( which I want to change ):
SELECT Products.ProductID, Products.AnticipatedSalesPattern, Convert(Char(10),Invoices.Date,103) As [date], Orders.Cost
FROM (Orders INNER JOIN Products ON Orders.ProductID = Products.ProductID)
INNER JOIN Invoices ON Orders.Invoice = Invoices.InvoiceNum
WHERE (Products.IsResource=1 AND Orders.Returned<>1 AND Orders.Cost<>0)
ORDER BY Products.ProductID, Invoices.Date;
Here is how it process the data(in asp), I know it's not effective just made it sample modeling data...
while not dbrecords.eof
RecordsCount = RecordsCount + 1
if dbrecords("ProductID") <> LastPID then
PIDsCount = PIDsCount + 1
LastPID = dbrecords("ProductID")
FirstSaleDate = dbrecords("Date")
if month(FirstSaleDate) < 9 then
FirstSchoolYear = Year(FirstSaleDate) - 1
else
FirstSchoolYear = Year(FirstSaleDate)
end if
end if
YearsSinceFirstSale = int(DateDiff("d",FirstSaleDate,dbrecords("Date"))/365)
MyArray(FirstSchoolYear-2000,YearsSinceFirstSale) = MyArray(FirstSchoolYear-2000,YearsSinceFirstSale) + dbrecords("Cost")
MyArrayTotals(FirstSchoolYear-2000) = MyArrayTotals(FirstSchoolYear-2000) + dbrecords("Cost")
TotalSales = TotalSales + dbrecords("Cost")
dbrecords.movenext
wend
Now what I like is to remove the whole process of putting the data into an array and the query to return the yearly data
What i'm curently stuck on is to write sql to pass the years since first sale and keeping track of each products (how to implement that in sql), I beleieve parameters are accepted via CTE statements...
Also if you think that this can be achieved some other way much effieciently that would be great too
Any help would be greatly appreciated...
So far I got to;
This doesn't provide with the identical data produced by the asp...and also let me know if there is a better way to do this...
DROP VIEW inline_view;
GO
CREATE VIEW inline_view AS
SELECT p2.ProductID, p2.AnticipatedSalesPattern, Invoices.Date, Orders.Cost, case when MONTH(date) < 9 then YEAR(date)-1 else YEAR(date) end as year,
(select top 1 case when MONTH(i.date) < 9 then YEAR(i.date)-1 else YEAR(i.date) end from Invoices i inner join Orders o on i.InvoiceNum=o.Invoice
inner join Products p on o.ProductID = p.ProductID where p2.ProductID = p.productID order by i.Date asc) as startsale
FROM (Orders INNER JOIN Products p2 ON Orders.ProductID = p2.ProductID)
INNER JOIN Invoices ON Orders.Invoice = Invoices.InvoiceNum
WHERE (p2.IsResource=1 AND Orders.Returned<>1 AND Orders.Cost<>0)
;
GO
SELECT * FROM (
select SUM(cost) sum, datediff(y, startsale, year) as year, startsale from inline_view
group by year, startsale
) as data
PIVOT
(
sum(sum)
--years after product is online
FOR year IN ([1], [2], [3],[4],[5],[6],[7],[8],[9], [10],[11], [12])
) as pvt;