Show Fiscal Year Dynamically - SQL - sql

I have created an Oracle SQL query that produces current year data:
SELECT A.ITEMNO, A.DESCRIP, SUM(RD.QTYRETURNED) AS "TOTAL QTY RETURNED"
FROM RMA R LEFT OUTER JOIN RMA_DETAIL RD ON R.ID=RD.RMA_ID
LEFT OUTER JOIN ARINVT A ON RD.ARINVT_ID=A.ID
LEFT OUTER JOIN ARCUSTO C ON C.ID = A.ARCUSTO_ID
WHERE ((R."CLOSED" IS NULL ) OR ((R.CLOSED='N' OR R.CLOSED='Y'))) AND
EXTRACT(YEAR FROM R.RMA_DATE) = EXTRACT(YEAR FROM SYSDATE)
GROUP BY A.ITEMNO, A.DESCRIP
ORDER BY "TOTAL QTY RETURNED" DESC
I am needed to create a query that returns our fiscal year (12/1 - 11/30) so I created this:
SELECT A.ITEMNO, A.DESCRIP, SUM(RD.QTYRETURNED) AS "TOTAL QTY RETURNED"
FROM RMA R LEFT OUTER JOIN RMA_DETAIL RD ON R.ID=RD.RMA_ID
LEFT OUTER JOIN ARINVT A ON RD.ARINVT_ID=A.ID
LEFT OUTER JOIN ARCUSTO C ON C.ID = A.ARCUSTO_ID
WHERE ((R."CLOSED" IS NULL ) OR ((R.CLOSED='N' OR R.CLOSED='Y'))) AND
R.RMA_DATE >= ADD_MONTHS(TRUNC(SYSDATE, 'MONTH'), -7) AND R.RMA_DATE <
ADD_MONTHS(TRUNC(SYSDATE, 'MONTH'), 5)
GROUP BY A.ITEMNO, A.DESCRIP
ORDER BY "TOTAL QTY RETURNED" DESC
These are queries that are used to create BI Dashboards. The issue with the fiscal year query is that when the sysdate month changes, then so will the data. What is the cleanest way to go about doing this? I'm just beginning with SQL, so any links to learning articles or explanations will go a long way. TIA

You can try a query like the one below. It calculates the "begin" and "end" dates based on what month you are currently in
SELECT A.ITEMNO, A.DESCRIP, SUM (RD.QTYRETURNED) AS "TOTAL QTY RETURNED"
FROM RMA R
LEFT OUTER JOIN RMA_DETAIL RD ON R.ID = RD.RMA_ID
LEFT OUTER JOIN ARINVT A ON RD.ARINVT_ID = A.ID
LEFT OUTER JOIN ARCUSTO C ON C.ID = A.ARCUSTO_ID
WHERE ((R."CLOSED" IS NULL) OR ((R.CLOSED = 'N' OR R.CLOSED = 'Y')))
AND R.RMA_DATE >=
TO_DATE (
CASE EXTRACT (MONTH FROM SYSDATE)
WHEN 12 THEN TO_CHAR (SYSDATE, 'YYYY')
ELSE TO_CHAR (ADD_MONTHS (SYSDATE, -12), 'YYYY')
END
|| '-12-01',
'YYYY-MM-DD')
AND R.RMA_DATE <
TO_DATE (
CASE EXTRACT (MONTH FROM SYSDATE)
WHEN 12 THEN TO_CHAR (ADD_MONTHS (SYSDATE, 12), 'YYYY')
ELSE TO_CHAR (SYSDATE, 'YYYY')
END
|| '-12-01',
'YYYY-MM-DD')
GROUP BY A.ITEMNO, A.DESCRIP
ORDER BY "TOTAL QTY RETURNED" DESC

Related

Aggregate functions are not allowed in GROUP BY

I want to generate a report based on a monthly count of records. In situations where there's none, I want to have 0 return instead of nothing. The issue is, the query below throws an error aggregate functions are not allowed in GROUP BY. Any help will be appreciated.
SELECT sc.name, d.months, COUNT(s.scan_type) AS scan_count FROM
(SELECT CAST('2018-02-21 12:45:44+00' AS TIMESTAMP) - date_trunc('month', CAST('2018-02-21 12:45:44+00' AS TIMESTAMP) - offs) AS months
FROM generate_series(CAST('2018-02-21 12:45:44+00' AS TIMESTAMP), CAST(now() AS TIMESTAMP), INTERVAL '1 month') AS offs ) d
LEFT OUTER JOIN scans s ON d.months = date_trunc('month', s.datetime)
INNER JOIN schools sc ON s.school_id = sc.id
GROUP BY sc.name, d.months, scan_count
Just use a NVL ?
For example
SELECT sc.name, d.months, NVL(COUNT(s.scan_type),COUNT(s.scan_type),0) AS scan_count FROM ...
If I understand correctly, use CROSS JOIN to combine all the dates and schools. Then bring in the original data and aggregate:
SELECT sc.name, d.months, COUNT(s.scan_type) AS scan_count
FROM generate_series(CAST('2018-02-21 12:45:44+00' AS TIMESTAMP),
CAST(now() AS TIMESTAMP),
INTERVAL '1 month'
) d CROSS JOIN
schools sc LEFT OUTER JOIN
scans s
ON d.months = date_trunc('month', s.datetime) AND
s.school_id = sc.id
GROUP BY sc.name, d.months;
Changing INNER JOIN to LEFT OUTER JOIN on schools fixed it. Also, I had to remove scan_count from the GROUP BY clause.
SELECT sc.name, d.months, COUNT(s.scan_type) AS scan_count FROM
(SELECT CAST('2018-02-21 12:45:44+00' AS TIMESTAMP) - date_trunc('month', CAST('2018-02-21 12:45:44+00' AS TIMESTAMP) - offs) AS months
FROM generate_series(CAST('2018-02-21 12:45:44+00' AS TIMESTAMP), CAST(now() AS TIMESTAMP), INTERVAL '1 month') AS offs ) d
LEFT OUTER JOIN scans s ON d.months = date_trunc('month', s.datetime)
LEFT OUTER JOIN schools sc ON s.school_id = sc.id
GROUP BY sc.name, d.months

Select all clients that have made a reservation each month in the previous year

I have to make an sql query that shows all the info of the clients that have made a reservation every single month in the last year, I thought about using a Group by Month and then count the number of groups.
Like this: (I didn't know how to count the number of groups)
Select *
From Cliente
inner join Persona
on Cliente.CEDULA = Persona.CEDULA
inner join Reserva
on Cliente.cedula = Reserva.CEDULA
Group BY DATEPART(MONTH, Reserva.FECHAINICIO);
Assuming that cedula identifies the client, you do not need all the joins. Then the key is the date arithmetic part and aggregation:
select r.cedula
from Reserva r
where r.fechainicio >= trunc(sysdate, 'YYYY') - interval '1' year and
f.fechainicio < trunc(sysdate, 'YYYY')
group by r.cedula
having count(distinct trunc(r.fechainicio, 'MM')) = 12;
Do you search for count()?
Select DATEPART(MONTH, Reserva.FECHAINICIO), count(*)
From Cliente
inner join Persona
on Cliente.CEDULA = Persona.CEDULA
inner join Reserva
on Cliente.cedula = Reserva.CEDULA
Group BY DATEPART(MONTH, Reserva.FECHAINICIO);
Try with bellow query, Put relevant column names for client.id_column, date_column
Select Month, COUNT(<<client.id_column>>) TotalCount
From Cliente
inner join Persona
on Cliente.CEDULA = Persona.CEDULA
inner join Reserva
on Cliente.cedula = Reserva.CEDULA
where Reserva.<<date_column>> >= '2017-01-01'
AND Reserva.<<date_column>> <= '2017-12-31'
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Reserva.<<date_column>>), 0), as Month;

storing result of a query based on the date in a rolling monthly table

I am trying to store the result of a query into a monthly table (last 30 days) based on dates.
Example for February 1st 2018: gives me a count of 310
SELECT *
FROM properties p
INNER JOIN orders o
ON o.property_id = p.id
WHERE o.type = 'Order::PromotedListing'
AND o.expired_at::DATE > '2018-02-01'
AND o.created_at::DATE <= '2018-02-01'
ORDER BY o.updated_at
For February 2nd 2018: gives me a count of 307
SELECT *
FROM properties p
INNER JOIN orders o
ON o.property_id = p.id
WHERE o.type = 'Order::PromotedListing'
AND o.expired_at::DATE > '2018-02-02'
AND o.created_at::DATE <= '2018-02-02'
ORDER BY o.updated_at
and so on.
I want to store these counts for last 30 days based on dates in a temp table/CTE. Something like this -
day, count
2018-02-01, 310
2018-02-02, 307
...
...
so I came up with this query but it is not doing what I am trying to do.
WITH monthly_dates AS (
SELECT d.date as day
FROM generate_series(current_date - interval '30 day',
current_date,
'1 day') AS d
),
featured_listings AS (
SELECT o.expired_at::date, o.created_at::date, o.updated_at::date
FROM properties p
INNER JOIN orders o
ON o.property_id = p.id
WHERE o.type = 'Order::PromotedListing'
)
SELECT m.day, COUNT(*)
FROM monthly_dates AS m
LEFT JOIN featured_listings AS f
ON m.day = f.updated_at
WHERE f.expired_at > m.day
AND f.created_at <= m.day
GROUP BY 1
ORDER BY 1;
Any input on accomplishing this task will be appreciated.
You seem to want:
SELECT g.dte, count(o.property_id)
FROM generate_series('2018-02-01'::date, '2018-02-28'::date, interval '1 day'
) g(dte) INNER JOIN
orders o
ON o.expired_at::DATE > g.dte AND o.created_at::DATE <= o.gte
GROUP BY g.dte
ORDER BY g.dte;
I don't think you need the properties table for this query.

Sum amount of table where a particular column has same value

I am trying to find the sum of amount in the table according to the value of month. This is my query
SELECT to_char(
to_timestamp(
date_part('month', p.date_from)::text,
'MM'
),
'Month'
) as Month,
p.employee_id, p.id as payslip_id,
p.date_from, p.date_to, pl.amount
FROM hr_payslip p
INNER JOIN hr_payslip_line pl
ON (p.id = pl.slip_id AND pl.code = 'NET');
Output:
Need:
I need to group by the month and sum value of column amount.
Perhaps a simple GROUP BY is all you are asking for:
SELECT to_char(p.date_from, 'Month') as month,
sum(pl.amount)
FROM hr_payslip p
INNER JOIN hr_payslip_line pl
ON (p.id = pl.slip_id AND pl.code = 'NET')
GROUP BY to_char(p.date_from, 'Month');
I did it using the following query
select to_char(to_timestamp (date_part('month', p.date_from)::text, 'MM'), 'Month') as Month,
sum(pl.amount) from hr_payslip p
INNER JOIN hr_payslip_line pl on (p.id = pl.slip_id and pl.code = 'NET') group by month
output:

Group by year month sql, when no entry write 0

I have an sql query, but I want to show months, where no entries. Now just show entries when it has entry. Here is the code:
SELECT YEAR(T0.[Recontact]) AS 'Év', MONTH(T0.[Recontact]) AS 'Hónap',
T1.[SlpName], COUNT(T0.[ClgCode]) AS 'Tárgyalások'
FROM OCLG T0
INNER JOIN OSLP T1 ON T0.[SlpCode] = T1.[SlpCode]
WHERE T0.[Action] = 'M' AND
T0.[Recontact] >= 'date' AND
T0.[Recontact] <= 'date2' AND
T1.[SlpName] = 'user name'
GROUP BY YEAR(T0.[Recontact]), MONTH(T0.[Recontact]), T1.[SlpName]
ORDER BY 1,2
If the year + month is totally missing from your data, you'll need to construct an empty row somewhere that can be shown in the place. You can create either a calendar table (one row per day) or a month table (one row per month). That can also be a "virtual" tally table constructed in a CTE or similar.
Once you have that, you can do something like this:
select
M.Year, M.Month, X.SlpName, isnull(X.CODES,0) as CODES
from
months M
outer apply (
SELECT
YEAR(T0.[Recontact]) as Year,
MONTH(T0.[Recontact]) AS Month,
T1.[SlpName],
COUNT(T0.[ClgCode]) AS CODES
FROM OCLG T0
INNER JOIN OSLP T1 ON T0.[SlpCode] = T1.[SlpCode]
WHERE T0.[Action] = 'M' AND
T0.[Recontact] >= 'date' AND
T0.[Recontact] <= 'date2' AND
T1.[SlpName] = 'user name'
GROUP BY YEAR(T0.[Recontact]), MONTH(T0.[Recontact]), T1.[SlpName]
) X on X.Year = M.Year and X.Month = M.Month
where M.MONTHDATE >= 'date' and M.MONTHDATE <= 'date2'
ORDER BY 1,2
This was with an imaginary month table that has year, month and monthdate columns, and the date is the first of the month -- you'll still have to check that the range you're fetching is correct.
I haven't tested this, but it should work.
Replace INNER JOIN with LEFT JOIN in your request to get NULL results.
SELECT YEAR(T0.[Recontact]) AS 'Év', MONTH(T0.[Recontact]) AS 'Hónap',
T1.[SlpName], COUNT(T0.[ClgCode]) AS 'Tárgyalások'
FROM OCLG T0
LEFT JOIN OSLP T1 ON (T0.[SlpCode] = T1.[SlpCode]
AND T1.[SlpName] = 'user name')
WHERE T0.[Action] = 'M'
AND T0.[Recontact] >= 'date'
AND T0.[Recontact] <= 'date2'
GROUP BY YEAR(T0.[Recontact]), MONTH(T0.[Recontact]), T1.[SlpName]
ORDER BY 1,2
Replace INNER JOIN with LEFT JOIN in your request to get NULL results.
to learn more visit :
http://academy.comingweek.com/sql-groupby-clause/