POSTGRESQL GROUP BY QUERY - sql

SELECT
concat(
EXTRACT(
YEAR
FROM
"BEAUFTRAGUNG_DATUM"
),
'-',
TO_CHAR(
EXTRACT(
MONTH
FROM
"BEAUFTRAGUNG_DATUM"
),
'fm00'
)
) AS "DATUM",
CASE
WHEN (
"STATUS" in (
'....', '...'
)
) THEN 'OTHER'
WHEN ("STATUS" = 'BESTELLT') THEN 'BESTELLT'
WHEN ("STATUS" = 'VOR_PRODUKTION') THEN 'VOR_PRODUKTION'
END AS "MODIFIED_STATUS",
COUNT(*) AS "ANZAHL"
FROM
PUBLIC."TXS"
WHERE
"FLAG_POS" = '1'
GROUP BY
"DATUM",
"MODIFIED_STATUS"
ORDER BY
"DATUM" ASC
This is what I have.
And I want it like this
DATUM OTHER BESTELLT VOR_PRODUKTION
2021-11 47 87 366
2022-01 1 0 0
2022-02 82 73 356
So that I have unique dates.
Thanks in advance.
I tried some solutions with "JOINS" but none of them worked.
I hope that you have any ideas...

This query should be able to get the desired result with the given information:
SELECT
txs.DATUM,
COALESCE(other.sum, 0) AS other,
COALESCE(bestellt.sum, 0) AS bestellt,
COALESCE(vor_produktion.sum, 0) AS vor_produktion
FROM
PUBLIC."TXS" txs
LEFT JOIN (SELECT tsx2.DATUM, SUM(tsx2.ANZAHL) AS sum FROM PUBLIC."TXS" tsx2 WHERE tsx2.MODIFIED_STATUS = 'OTHER' GROUP BY tsx2.DATUM) other ON other.DATUM = txs.DATUM
LEFT JOIN (SELECT tsx2.DATUM, SUM(tsx2.ANZAHL) AS sum FROM PUBLIC."TXS" tsx2 WHERE tsx2.MODIFIED_STATUS = 'BESTELLT' GROUP BY tsx2.DATUM) bestellt ON bestellt.DATUM = txs.DATUM
LEFT JOIN (SELECT tsx2.DATUM, SUM(tsx2.ANZAHL) AS sum FROM PUBLIC."TXS" tsx2 WHERE tsx2.MODIFIED_STATUS = 'VOR_PRODUKTION' GROUP BY tsx2.DATUM) vor_produktion ON vor_produktion.DATUM = txs.DATUM
GROUP BY txs.DATUM, other.sum, bestellt.sum, vor_produktion.sum
Here we left join the 3 columns with a subquery and replaces <null> values with 0

Related

SELECT list expression references column integration_start_date which is neither grouped nor aggregated at

I'm facing an issue with the following query. It gave me this error [SELECT list expression references column integration_start_date which is neither grouped nor aggregated at [34:63]]. In particular, it points to the first 'when' in the result table, which I don't know how to fix. This is on BigQuery if that helps. I see everything is written correctly or I could be wrong. Seeking for help.
with plan_data as (
select format_date("%Y-%m-%d",last_day(date(a.basis_date))) as invoice_date,
a.sponsor_id as sponsor_id,
b.company_name as sponsor_name,
REPLACE(SUBSTR(d.meta,STRPOS(d.meta,'merchant_id')+12,13),'"','') as merchant_id,
a.state as plan_state,
date(c.start_date) as plan_start_date,
a.employee_id as square_employee_id,
date(
(select min(date)
from glproductionview.stats_sponsors
where sponsor_id = a.sponsor_id and sponsor_payroll_provider_identifier = 'square' and date >= c.start_date) )
as integration_start_date,
count(distinct a.employee_id) as eligible_pts_count, --pts that are in active plan and have payroll activities (payroll deductions) in the reporting month
from glproductionview.payroll_activities as a
left join glproductionview.sponsors as b
on a.sponsor_id = b.id
left join glproductionview.dc_plans as c
on a.plan_id = c.id
left join glproductionview.payroll_connections as d
on a.sponsor_id = d.sponsor_id and d.provider_identifier = 'rocket' and a.company_id = d.payroll_id
where a.payroll_provider_identifier = 'rocket'
and format_date("%Y-%m",date(a.basis_date)) = '2021-07'
and a.amount_cents > 0
group by 1,2,3,4,5,6,7,8
order by 2 asc
)
select invoice_date,
sponsor_id,
sponsor_name,
eligible_pts_count,
case
when eligible_pts_count <= 5 and date_diff(current_date(),integration_start_date, month) <= 12 then 20
when eligible_pts_count <= 5 and date_diff(current_date(),integration_start_date, month) > 12 then 15
when eligible_pts_count > 5 and date_diff(current_date(),integration_start_date, month) <= 12 then count(distinct square_employee_id)*4
when eligible_pts_count > 5 and date_diff(current_date(),integration_start_date, month) > 12 then count(distinct square_employee_id)*3
else 0
end as fees
from plan_data
group by 1,2,3,4;

Subqueries Condition (SQL)

So i want to create a view using the below script the problem is i want to show the view for 2020 grouped by quarter as you can see i have 2 subqueries using to_char(ACTION_DATE,'YYYY') = 2020 I want to return quarter results ONLY if FileNO's in both subqueries are from the Same Quarter.
SELECT Quarter,
count(FileNO), avg(total_time),
sum( case when Total_Time <= :T Then 1 Else 0 End ) Achieved,
sum( case when Total_Time <= :T Then 1 Else 0 End ) / Count(FileNO) * 100 Precentage_Acheived
from
(SELECT to_Char(ACTION_DATE,'YYYYQ') as Quarter, FileNO, SUM(work_time) as total_time
FROM F.MV
WHERE
(FileNO, APP_no) IN
(SELECT FileNO, APP_no
FROM F.MV
WHERE to_char(ACTION_DATE,'YYYY') = 2020
AND TASK_NAME = 'Lifting'
AND TO_TASK_NAME = 'Finish')
AND DEPT_NAME = 'TempDep'
AND WF_TASK_NAME = 'Lifting'
and to_char(ACTION_DATE,'YYYY') = 2020
GROUP BY to_Char(ACTION_DATE,'YYYYq'),FileNO
)
GROUP BY Quarter
Correct if i use to_char(ACTION_DATE,'YYYYQ') = 20201 for both subquieres
but result iam getting with to_char(ACTION_DATE,'YYYY') = 2020 is:
Thanks
I think the innermost correlation clause you want is:
(FileNO, APP_no) IN
(SELECT mv2.FileNO, mv2.APP_no
FROM F.MV mv2
WHERE to_char(mv2.ACTION_DATE, 'YYYYQ') = to_char(mv.ACTION_DATE, 'YYYYQ')

Simplify complex Query

I need to simplify a complex old query in order to filter is with date range.
I got a table with Tickets and TicketNotes.
I need
a column with the Tickets count of the day
a column with the Tickets count with a specific note of the day
the date
The old query
SELECT SUM(IFNULL(qtickets.count, 0)) j, SUM(IFNULL(mtickets.count, 0)) m FROM (
SELECT
COUNT(tickets.id) COUNT,
DATE(tickets.date) DATE
FROM
tickets
WHERE
tickets.status = 'Closed' AND tickets.did = 7
AND MONTH(tickets.date) = MONTH( CURRENT_DATE - INTERVAL 1 MONTH )
AND YEAR(tickets.date) = YEAR( CURRENT_DATE - INTERVAL 1 MONTH )
GROUP BY
DATE(tickets.date)
) AS mtickets LEFT JOIN (
SELECT
1 AS COUNT,
DATE(tickets.date) DATE
FROM
ticketnotes
INNER JOIN tickets ON tickets.id = ticketnotes.ticketid
WHERE
ticketnotes.message LIKE '%https://xxxxx.net/help/tickets/%'
AND tickets.status = 'Closed'
AND tickets.did = 7
AND MONTH(tbltickets.date) = MONTH( CURRENT_DATE - INTERVAL 1 MONTH )
AND YEAR(tbltickets.date) = YEAR( CURRENT_DATE - INTERVAL 1 MONTH )
GROUP BY
DATE(tickets.date)
) AS qtickets ON (mtickets.date = qtickets.date)
The goal is to get a result of
Date | M | Q
===================
2020-04-01 | 1 | 1
2020-04-02 | 2 | 1
2020-04-03 | 5 | 2
...
2020-04-30 | 3 | 0
With M be the total closed tickets of the day for did = 7 and Q be the total closed tickets that got the note.message.
I need to check the query with one instance of date filter date BETWEEN '2020-04-01' AND '2020-04-30' and still get the correct three columns.
=======
UPDATE:
When I'm trying to add AND DATE(tickets.date) BETWEEN DATE('2020-04-01') AND DATE('2020-04-30') in Gordon's answer, I got other result data from my primary query.
QUERY:
SELECT
DATE(t.date),
COUNT(t.id) AS num_tickets,
(CASE WHEN COUNT(tn.ticketid) = 0 THEN 0 ELSE 1 END) AS num_with_message
FROM
tickets t
LEFT JOIN ticketnotes tn ON
tn.ticketid = t.id AND tn.message LIKE '%https://xxxxx.net/help/tickets/%'
WHERE
t.status = 'Closed' AND t.did = 7
AND DATE(t.date) BETWEEN DATE('2020-04-01') AND DATE('2020-04-30')
GROUP BY
DATE(t.date)
The result is getting num_tickets with wrong data as getting num_ticket without JOIN.
Any suggestions ?
You could try using case for the ehere like
SELECT
DATE(tickets.date) DATE
, COUNT(tickets.id) M
, case sum( ticketnotes.message LIKE '%https://xxxxx.net/help/tickets/%' <> 0 ) then 1 else null end Q
FROM
ticketnotes
INNER JOIN tickets ON tickets.id = ticketnotes.ticketid
WHERE tickets.status = 'Closed'
AND tickets.did = 7
AND MONTH(tbltickets.date) = MONTH( CURRENT_DATE - INTERVAL 1 MONTH )
AND YEAR(tbltickets.date) = YEAR( CURRENT_DATE - INTERVAL 1 MONTH )
GROUP BY DATE(tickets.date)
This answers the original version of the question.
What you are describing sounds like a group by with left join. However, it is not clear what exactly you are looking for. My best guess is:
select date(t.date), count(t.id) as num_tickets,
count(tn.ticketid) as num_with_message
from tickets t left join
ticketnotes tn
on tn.ticketid = t.id and
tn.message like '%https://xxxxx.net/help/tickets/%'
where t.status = 'Closed' and
t.did = 7
group by date(t.date)

MS SQL - JOIN show months that doesn't have data

I am having a new problem with SQL JOINS.
Here is my scenario.
I have a report, where I need to show sales performance for a specific customer.
The report shows the sales performance per month.
Please look at my result set:
This is the sales report for customer AFP035. As you can see there are months that are not showing. I am required to include those months that doesn't have data(NULL).
Here what I have tried. I created a month table where I maintained the months.
And then I did a LEFT JOIN. Seems strange because it doesn't show the desired result. From what I understand LEFT JOIN should show the NULL values. And I am wrong.
Please see my query:
select CustNm as company,
Cust as customer,
Cust as custCode,
Mon,
case
when Mon = 1 THEN 'January'
when Mon = 2 THEN 'February'
when Mon = 3 THEN 'March'
when Mon = 4 THEN 'April'
when Mon = 5 THEN 'May'
when Mon = 6 THEN 'June'
when Mon = 7 THEN 'July'
when Mon = 8 THEN 'August'
when Mon = 9 THEN 'September'
when Mon = 10 THEN 'October'
when Mon = 11 THEN 'November'
when Mon = 12 THEN 'December'
end as 'month',
Yr as 'year',
Mon as monthCheck,
case
when NetSales IS NULL THEN 0
else NetSales
end as netSales,
case
when PrvYrSales IS NULL THEN 0
else PrvYrSales
end as prevYearSales,
case
when SalesGrwth IS NULL THEN 0
else SalesGrwth * 100
end as salesGrowth,
case
when YrBfrLst IS NULL THEN 0
else YrBfrLst
end as yearBeforeLast,
case
when BfrLstGrwth IS NULL THEN 0
else BfrLstGrwth * 100
end as yearBeforeLastGrowth
from BigEMasterData.dbo.monthtmp as a
left outer join BigESales.dbo.tbl_ReportCOMPANYperCust as b
on b.Mon = a.monthNo
or b.Mon is null
The result is the screenshot above.
Would you help me with this or at least enlighten me why I am not getting the desired result?
Thank you so much. Any suggestion would be highly appreciated.
EDIT: SOLVED: with Yogesh's help Thankyou.
;WITH CTE AS (
SELECT * FROM tbl_ReportCOMPANYperCust r
WHERE Cust = 'AFP035'
and Yr = 2016
)
SELECT
r.CustNm as company, r.Cust as customer, r.Cust as custCode,
a.monthNo, a.monthName, r.Yr as Year,
COALESCE(NetSales, 0) as netSales,
COALESCE(PrvYrSales, 0) as prevYearSales,
COALESCE(SalesGrwth*100, 0) as salesGrowth,
COALESCE(YrBfrLst, 0) as yearBeforeLast,
COALESCE(BfrLstGrwth*100, 0) as yearBeforeLastGrowth
FROM BigEMasterData.dbo.monthtmp a
LEFT OUTER JOIN CTE r on r.Mon = a.monthNo
Here is the result. :
Let me correct your query, in order to get the all months then your calendar table should first table
SELECT
r.CustNm as company, r.Cust as customer, r.Cust as custCode,
a.monthNo, a.MontName, r.Yr as Year,
COALESCE(NetSales, 0) as netSales,
COALESCE(PrvYrSales, 0) as prevYearSales,
COALESCE(SalesGrwth*100, 0) as salesGrowth,
COALESCE(YrBfrLst, 0) as yearBeforeLast,
COALESCE(BfrLstGrwth*100, 0) as yearBeforeLastGrowth
FROM monthtmp a
LEFT OUTER JOIN tbl_ReportCOMPANYperCust r on r.Mon = a.monthNo
Use ANSI SQL Standard COALESCE() function to check NULL values
In order to get all months name use CTE or Subquery which could hold the filtered records
;WITH CTE AS (
SELECT * FROM tbl_ReportCOMPANYperCust r
WHERE Cust = 'AFP035'
and Yr = 2016
)
SELECT
COLAESCE(r.CustNm, LAG(r.CustNm) OVER (ORDER BY a.monthNo)) as company,
COLAESCE(r.Cust, LAG(r.Cust) OVER (ORDER BY a.monthNo)) as customer,
COLAESCE(r.Cust, LAG(r.Cust) OVER (ORDER BY a.monthNo)) as custCode,
a.monthNo, a.monthName, r.Yr as Year,
COALESCE(NetSales, 0) as netSales,
COALESCE(PrvYrSales, 0) as prevYearSales,
COALESCE(SalesGrwth*100, 0) as salesGrowth,
COALESCE(YrBfrLst, 0) as yearBeforeLast,
COALESCE(BfrLstGrwth*100, 0) as yearBeforeLastGrowth
FROM BigEMasterData.dbo.monthtmp a
LEFT OUTER JOIN CTE r on r.Mon = a.monthNo
You would appear to want:
SELECT c.company, c.customer, c.custCode,
m.monthNo, m.monthName, c.Year,
COALESCE(r.NetSales, 0) as netSales,
COALESCE(r.PrvYrSales, 0) as prevYearSales,
COALESCE(r.SalesGrwth*100, 0) as salesGrowth,
COALESCE(r.YrBfrLst, 0) as yearBeforeLast,
COALESCE(r.BfrLstGrwth*100, 0) as yearBeforeLastGrowth
FROM (SELECT DISTINCT r.CustNm as company, r.Cust as customer, r.Cust as custCode, r.Yr as Year
FROM tbl_ReportCOMPANYperCust
WHERE c.Cust = 'AFP035'
) c CROSS JOIN
BigEMasterData.dbo.monthtmp m LEFT OUTER JOIN
tbl_ReportCOMPANYperCust r
ON r.Mon = m.monthNo AND r.Cust = c.customer
ORDER BY m.monthNo;
Notice the CROSS JOIN. This brings in the initial columns, so you have them even for months that do not match the data.

SQL Query in CRM Report

A "Case" in CRM has a field called "Status" with four options.
I'm trying to
build a report in CRM that fills a table with every week of the year (each row is a different week), and then counts the number of cases that have each Status option (the columns would be each of the Status options).
The table would look like this
Status 1 Status 2 Status 3
Week 1 3 55 4
Week 2 5 23 5
Week 3 14 11 33
So far I have the following:
SELECT
SUM(case WHEN status = 1 then 1 else 0 end) Status1,
SUM(case WHEN status = 2 then 1 else 0 end) Status2,
SUM(case WHEN status = 3 then 1 else 0 end) Status3,
SUM(case WHEN status = 4 then 1 else 0 end) Status4,
SUM(case WHEN status = 5 then 1 else 0 end) Status5
FROM [DB].[dbo].[Contact]
Which gives me the following:
Status 1 Status 2 Status 3
2 43 53
Now I need to somehow split this into 52 rows for the past year and filter these results by date (columns in the Contact table). I'm a bit new to SQL queries and CRM - any help here would be much appreciated.
Here is a SQLFiddle with my progress and sample data: http://sqlfiddle.com/#!2/85b19/1
Sounds like you want to group by a range. The trick is to create a new field that represents each range (for you one per year) and group by that.
Since it also seems like you want an infinite range of dates, marc_s has a good summary for how to do the group by trick with dates in a generic way: SQL group by frequency within a date range
So, let's break this down:
You want to make a report that shows, for each contact, a breakdown, week by week, of the number of cases registered to that contact, which is divided into three columns, one for each StateCode.
If this is the case, then you would need to have 52 date records (or so) for each contact. For calendar like requests, it's always good to have a separate calendar table that lets you query from it. Dan Guzman has a blog entry that creates a useful calendar table which I'll use in the query.
WITH WeekNumbers AS
(
SELECT
FirstDateOfWeek,
-- order by first date of week, grouping calendar year to produce week numbers
WeekNumber = row_number() OVER (PARTITION BY CalendarYear ORDER BY FirstDateOfWeek)
FROM
master.dbo.Calendar -- created from script
GROUP BY
FirstDateOfWeek,
CalendarYear
), Calendar AS
(
SELECT
WeekNumber =
(
SELECT
WeekNumber
FROM
WeekNumbers WN
WHERE
C.FirstDateOfWeek = WN.FirstDateOfWeek
),
*
FROM
master.dbo.Calendar C
WHERE
CalendarDate BETWEEN '1/1/2012' AND getutcdate()
)
SELECT
C.FullName,
----include the below if the data is necessary
--Cl.WeekNumber,
--Cl.CalendarYear,
--Cl.FirstDateOfWeek,
--Cl.LastDateOfWeek,
'Week: ' + CAST(Cl.WeekNumber AS VARCHAR(20))
+ ', Year: ' + CAST(Cl.CalendarYear AS VARCHAR(20)) WeekNumber
FROM
CRM.dbo.Contact C
-- use a cartesian join to produce a table list
CROSS JOIN
(
SELECT
DISTINCT WeekNumber,
CalendarYear,
FirstDateOfWeek,
LastDateOfWeek
FROM
Calendar
) Cl
ORDER BY
C.FullName,
Cl.WeekNumber
This is different from the solution Ben linked to because Marc's query only returns weeks where there is a matching value, whereas you may or may not want to see even the weeks where there is no activity.
Once you have your core tables of contacts split out week by week as in the above (or altered for your specific time period), you can simply add a subquery for each StateCode to see the breakdown in columns as in the final query below.
WITH WeekNumbers AS
(
SELECT
FirstDateOfWeek,
WeekNumber = row_number() OVER (PARTITION BY CalendarYear ORDER BY FirstDateOfWeek)
FROM
master.dbo.Calendar
GROUP BY
FirstDateOfWeek,
CalendarYear
), Calendar AS
(
SELECT
WeekNumber =
(
SELECT
WeekNumber
FROM
WeekNumbers WN
WHERE
C.FirstDateOfWeek = WN.FirstDateOfWeek
),
*
FROM
master.dbo.Calendar C
WHERE
CalendarDate BETWEEN '1/1/2012' AND getutcdate()
)
SELECT
C.FullName,
--Cl.WeekNumber,
--Cl.CalendarYear,
--Cl.FirstDateOfWeek,
--Cl.LastDateOfWeek,
'Week: ' + CAST(Cl.WeekNumber AS VARCHAR(20)) +', Year: ' + CAST(Cl.CalendarYear AS VARCHAR(20)) WeekNumber,
(
SELECT
count(*)
FROM
CRM.dbo.Incident I
INNER JOIN CRM.dbo.StringMap SM ON
I.StateCode = SM.AttributeValue
INNER JOIN
(
SELECT
DISTINCT ME.Name,
ME.ObjectTypeCode
FROM
CRM.MetadataSchema.Entity ME
) E ON
SM.ObjectTypeCode = E.ObjectTypeCode
WHERE
I.ModifiedOn >= Cl.FirstDateOfWeek
AND I.ModifiedOn < dateadd(day, 1, Cl.LastDateOfWeek)
AND E.Name = 'incident'
AND SM.AttributeName = 'statecode'
AND SM.LangId = 1033
AND I.CustomerId = C.ContactId
AND SM.Value = 'Active'
) ActiveCases,
(
SELECT
count(*)
FROM
CRM.dbo.Incident I
INNER JOIN CRM.dbo.StringMap SM ON
I.StateCode = SM.AttributeValue
INNER JOIN
(
SELECT
DISTINCT ME.Name,
ME.ObjectTypeCode
FROM
CRM.MetadataSchema.Entity ME
) E ON
SM.ObjectTypeCode = E.ObjectTypeCode
WHERE
I.ModifiedOn >= Cl.FirstDateOfWeek
AND I.ModifiedOn < dateadd(day, 1, Cl.LastDateOfWeek)
AND E.Name = 'incident'
AND SM.AttributeName = 'statecode'
AND SM.LangId = 1033
AND I.CustomerId = C.ContactId
AND SM.Value = 'Resolved'
) ResolvedCases,
(
SELECT
count(*)
FROM
CRM.dbo.Incident I
INNER JOIN CRM.dbo.StringMap SM ON
I.StateCode = SM.AttributeValue
INNER JOIN
(
SELECT
DISTINCT ME.Name,
ME.ObjectTypeCode
FROM
CRM.MetadataSchema.Entity ME
) E ON
SM.ObjectTypeCode = E.ObjectTypeCode
WHERE
I.ModifiedOn >= Cl.FirstDateOfWeek
AND I.ModifiedOn < dateadd(day, 1, Cl.LastDateOfWeek)
AND E.Name = 'incident'
AND SM.AttributeName = 'statecode'
AND SM.LangId = 1033
AND I.CustomerId = C.ContactId
AND SM.Value = 'Canceled'
) CancelledCases
FROM
CRM.dbo.Contact C
CROSS JOIN
(
SELECT
DISTINCT WeekNumber,
CalendarYear,
FirstDateOfWeek,
LastDateOfWeek
FROM
Calendar
) Cl
ORDER BY
C.FullName,
Cl.WeekNumber