How group by month - sql

I'm having trouble finding out how to group by month-year. The below has error,
Not a group by expression
select
dcst.stateid as stateId,
dcst.crtdt ,
to_char(to_date(DCST.CRTDT,'DD-MON-YY HH.MI.SS."000000000" AM'),'Month') AS Month,
to_date(DCST.CRTDT,'DD-MON-YY HH.MI.SS."000000000" AM') as datetimes
from
TBL dcst
group by to_char(to_date(DCST.CRTDT,'MON-YY HH.MI.SS."000000000" AM'),'MON-YY')
This is an example of the dates in the table (the result of the above query without the group by):
Stateid CRTDT MONTH DATETIMES
506 22-DEC-22 06.08.17.480000000 PM December 22-DEC-22
506 23-DEC-22 10.11.00.795000000 AM December 23-DEC-22
853 10-JAN-23 12.30.45.212000000 AM January 04-JAN-23
I seem to be doing what this thread suggests is correct for group by month/year.
I'm testing in Oracle Sql Developer, but eventually will be testing on a Microsoft SQL db that isn't easily accessed on devices.
Update:
I added the StateId that I want to do a count by month, but doing a count by that gives the error "not a single-group group function". This error happens without the group by month part added with it.
Update2:
I'm trying to remove extra things from my query and get 'Group function is not allowed here'.
select
dcst.stateid as stateId,
dcst.crtdt
from tbl dcst
group by count(dcst.stateid), to_char(to_date(DCST.CRTDT,'MON-YY HH.MI.SS."000000000" AM'),'MON-YY')
expected output would be (I think):
12-22
2
01-23
1

CREATE TABLE dcst
(STATEID, CRTDT) AS
SELECT 506, TIMESTAMP '2022-12-22 06:08:17.480000' FROM DUAL UNION ALL
SELECT 506, TIMESTAMP'2022-12-23 10:11:00.480000' FROM DUAL UNION ALL
SELECT 853,TIMESTAMP'2023-01-10 10:11:00.480000' FROM DUAL
select to_char(crtdt, 'YYYY/MM'),
count(*)
from dcst
group by to_char(crtdt, 'YYYY/MM')
order by to_char(crtdt, 'YYYY/MM')
TO_CHAR(CRTDT,'YYYY/MM') COUNT(*)
2022/12 2
2023/01 1

Related

SQL Snowflake Min Date For Each Record & Group By Month

I am using Snowflake to get some information from the data. I have a table in which the same employee (PRS_ID) can be included in many rows and I want to take the EARLIEST date (BGN_DATE) for each employee (PRS_ID). Next, I want to see how many employees I have each month.
Ideally if I could have in YYYY-MM format (YYYYMM will work too). What I was working with is below:
SELECT PRS_ID, MIN(BGN_DATE), MONTH(BGN_DATE)
FROM myTable
WHERE EMP_STS = 'T'
GROUP BY PRS_ID, MONTH(BGN_DATE)
However, this will show me the data per employee (PRS_ID), which is too granular (as explained above). But when I remove "PRS_ID" from grouping I get below error:
SQL compilation error: error line 1 at position 7 'myTable.PRS_ID' in select clause is neither an aggregate nor in the group by clause.
Does anyone know how to fix it?
Thank you
Sample Data:
PRS_ID
EMP_STS
BGN_DATE
homsimps
T
2022-01-30
homsimps
T
2022-02-28
homsimps
T
2022-03-30
bartsimps
T
2022-01-30
bartsimps
T
2022-02-28
bartsimps
T
2022-03-31
lisasimps
T
2022-04-30
lisasimps
T
2022-05-31
lisasimps
T
2022-06-30
lisasimps
T
2022-07-30
margesimps
T
2022-02-28
margesimps
T
2022-03-30
Expected Outcome:
Period
Count
2022-01
2
2022-02
1
2022-03
0
2022-04
1
Using aggregation twice:
WITH cte AS (
SELECT PRR_ID, MIN(BGN_DATE) AS min_bgn_date
FROM my_table
WHERE EMP_STS = 'T'
GROUP BY PRS_ID
)
SELECT TO_VARCHAR(min_bgn_date, 'YYYYMM') AS month, COUNT(*) AS cnt
FROM cte
GROUP BY TO_VARCHAR(min_bgn_date, 'YYYYMM');
-- GROUP BY month
There is a simpler function here, DATE_TRUNC will allow you to convert dates to months. You can then convert to the format you'd like.
WITH MY_CTE AS (
SELECT
PRS_ID,
DATE_TRUNC(MONTH, MIN(BGN_DATE)) AS MONTH_START
FROM
myTable
WHERE
EMP_STS = 'T'
GROUP BY 1
)
SELECT
TO_CHAR(MONTH_START, 'yyyy-mm') AS PERIOD,
COUNT(PRS_ID)
GROUP BY 1

How to filter the last 7 days based on the previous query? -BigQuery

Hi I just want to ask how to resolve this problem.
Example in the query indicated below.
In the next query I will prepare, I want to filter the last 7 days of the delivery date. Do not use current_date because the maximum date is very late.
Assuming the current date is 7/12/2022 but the query shows a maximum date of 7/07/2022. How can I filter the date from 7/1/2022 to 7/07/2022?
, Datas1 as
(select distinct (delivery_due_date) as delivery_date
, Specialist
, Id_number
, Staff_Total as Total_Items
from joining
where Delivery_Due_Date is not null
)
Actually I used max function in where but I get an error. Please help me.
Created Examples of such data in first block.
Performed the select on that data in second block.
Extracted Maximum Delivery data in 3rd Block.
Restricted last block for 7 days of data collected from 3rd block.
WITH joining AS(
SELECT '2022-07-01' AS delivery_due_date, 'ABC' as Specialist,222 as Id_number, 21 as Staff_Total union all
SELECT '2022-07-07' AS delivery_due_date, 'ABC2' as Specialist,223 as Id_number, 01 as Staff_Total union all
SELECT '2022-07-15' AS delivery_due_date, 'ABC4' as Specialist,212 as Id_number, 25 as Staff_Total union all
SELECT '2022-07-20' AS delivery_due_date, 'AB5C' as Specialist,224 as Id_number, 15 as Staff_Total union all
SELECT '2022-07-05' AS delivery_due_date, 'ABC7' as Specialist,226 as Id_number, 87 as Staff_Total ),
Datas1 as (select distinct (delivery_due_date) as delivery_date , Specialist
, Id_number , Staff_Total as Total_Items from joining where Delivery_Due_Date is not null ),
Datas2 as (
select max(delivery_date) as ddd from Datas1)
select Datas1.* from Datas1,Datas2 where date(delivery_date) between date_sub(date(Datas2.ddd), interval 7 day) and date(Datas2.ddd)

order records by month name

i want to order my results by month name but it is not getting ordered in sql server .
my query:
select DATEname(month,signdate) as month1,
COUNT(contractid) as noofcontracts, sum(loanamt) as totalloan ,
min(loanamt) as minloan
from contracts
group by DATEname(month,signdate) order by DATEname(month, signdate);
i have tried using datepart function but then it is giving error
select DATEname(month,signdate) as month1,
COUNT(contractid) as noofcontracts, sum(loanamt) as totalloan ,
min(loanamt) as minloan
from contracts
group by DATEname(month,signdate)
order by DATEPART(m,signdate) ;
error:Column "contracts.signdate" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.
output which im getting:
month count loan_amt min_loan
April 2 14998 4999
February 1 8189 8189
June 5 133645 2599
May 2 21947 10048
Desired output:
February record should come first and so on..
Pls help.
Try using an aggregation function for the order by:
order by min(signdate);
Alternatively, include the month number in the group by:
group by datename(month, signdate), month(signdate)
order by month(signdate)
Note that you have the month in the query without the year -- either as a filter or a group by expression. This usually indicates an problem with the query logic.

SQL moving average with calc of average price per square metre

I'm trying to get a moving average for a set of real estate data that I can then graph, using MS SQL 2005.
Fields are: DateSold datetime, FloorSQM decimal(8,2), Price decimal(10,0)
What I need to do is get an average price per square metres of all the properties sold within each month as far back as we have data, which can be several years.
Therefore I need to Price/FloorSQM each property, and then apply a moving average to them for each month. Hope that makes sense.
I am completely stuck trying to figure this out, and googling endlessly is endlessly confusing.
I thought I found what I'm looking for in another post, but I keep getting "incorrect syntax near 'm'" when I try to compile it.
SELECT YEAR(DateSold) AS year,
MONTH(DateSold) AS month,
ROUND(Euros/CONVERT(DECIMAL(10,2),FloorSQM),2) as avg
FROM
(select s.*, DATE_ADD(DTE, INTERVAL m.i MONTH) DateSold, m.i
FROM Property s
cross join (select 0 i union select 1 union select 2 union select 3 union
select 4 union select 5 union select 6 union select 7 union
select 8 union select 9 union select 10 union select 11) m) sq
WHERE DateSold <= curdate()
GROUP BY YEAR(DateSold), MONTH(DateSold)
When I have this working, I then need to introduce a WHERE clause so I can limit the properties found to certain kinds (houses, apartments) and areas (New York, Los Angeles, etc)
Can anyone lend a hand please? Many thanks for your help.
This should run, you were using some Mysql syntax:
SELECT YEAR(DateSold) AS year,
MONTH(DateSold) AS month,
ROUND(Euros/CONVERT(DECIMAL(10,2),FloorSQM),2) as avg
FROM (SELECT s.*, DATEADD(MONTH,m.i,DateSold) DateSold2, m.i
FROM Property s
cross join (select 0 i union select 1 union select 2 union select 3 union
select 4 union select 5 union select 6 union select 7 union
select 8 union select 9 union select 10 union select 11
) m
)sq
WHERE DateSold<= GETDATE()
GROUP BY YEAR(DateSold), MONTH(DateSold)
Not sure if it returns the desired results.
Update: I thought DTE was a field name, you can't have DateSold referenced twice in your subquery, so I changed to DateSold2, not sure if you intend for the DATEADD() result to be used in all places where DateSold is used, you could also just remove DateSold from your subquery SELECT list.
Try this:
SELECT YEAR(DateSold) AS year,
MONTH(DateSold) AS month,
AVG(ROUND(Price/CONVERT(DECIMAL(10,2),FloorSQM),2)) as avg
FROM property p
GROUP BY YEAR(DateSold), MONTH(DateSold);
Note, changed the query from Euros to Price, as you specified in the schema.
The grouping of year, month is all you need to get the average of the price for that month. You were missing the aggregate function, AVG around your formula (though might be more accurate if ROUND was wrapped around AVG). I set up a quick sample at SQLFiddle.

How to Group SQL Results by Date in the Actual Order that they Appear in the Year in Oracle?

I'm trying to figure out how I can group the SQL results from a table in Oracle in the actual order in which the month occurred instead of the alphabet order of their names.
Can anyone help me with this? Thanks in advanced.
============ UPDATE ============
Here's an example query:
SELECT exec_month FROM table_or_view WHERE condition=1 GROUP BY exec_month;
You see, the problem is that I can't group by month like I want to. Just as Vincent Malgrat said, "Grouping has no implied order".
Grouping has no implied order. Add an ORDER BY clause if you want to display the rows in a certain order:
SQL> with data as (
2 SELECT add_months(trunc(sysdate, 'year'), rownum-1) dt
3 FROM dual CONNECT BY LEVEL <= 4
4 )
5 select to_char(dt, 'month')
6 from data
7 group by to_char(dt, 'month'), trunc(dt, 'month')
8 order by trunc(dt, 'month');
TO_CHAR(D
---------
january
february
march
april