Oracle SQL group by to_char - not a group by expression - sql

I want to group by dd-mm-yyyy format to show working_hours per employee (person) per day, but I get error message ORA-00979: not a GROUP BY expression, when I remove TO_CHAR from GROUP BY it works fine, but that's not I want as I want to group by days regardless hours, what am I doing wrong here?
SELECT papf.person_number emp_id,
to_char(sh21.start_time,'dd/mm/yyyy') start_time,
to_char(sh21.stop_time,'dd/mm/yyyy') stop_time,
SUM(sh21.measure) working_hours
FROM per_all_people_f papf,
hwm_tm_rec sh21
WHERE ...
GROUP BY
papf.person_number,
to_char(sh21.start_time,'dd/mm/yyyy'),
to_char(sh21.stop_time,'dd/mm/yyyy')
ORDER BY sh21.start_time

ORDER BY sh21.start_time
needs to either be just the column alias defined in the SELECT clause:
ORDER BY start_time
or use the expression in the GROUP BY clause:
ORDER BY to_char(sh21.start_time,'dd/mm/yyyy')
If you use sh21.start_time then the table_alias.column_name syntax refers to the underlying column from the table and you are not selecting/grouping by that.

Related

DATE_TRUNC with :: and without

The query only works when there is :: DATE.
-- Wrap the query you wrote in a CTE named reg_dates
WITH reg_dates AS (
SELECT
user_id,
MIN(order_date) AS reg_date
FROM orders
GROUP BY user_id)
SELECT
-- Count the unique user IDs by registration month
DATE_TRUNC('month', reg_date) :: DATE AS delivr_month,
COUNT(DISTINCT user_id) AS regs
FROM reg_dates
GROUP BY delivr_month
ORDER BY delivr_month ASC;
Why is that required? When I run the query below, without :: DATE, it does not work.
-- Wrap the query you wrote in a CTE named reg_dates
WITH reg_dates AS (
SELECT
user_id,
MIN(order_date) AS reg_date
FROM orders
GROUP BY user_id)
SELECT
-- Count the unique user IDs by registration month
DATE_TRUNC('month', reg_date) AS delivr_month,
COUNT(DISTINCT user_id) AS regs
FROM reg_dates
GROUP BY delivr_month
ORDER BY delivr_month ASC;
Highly likely your RDBMS is PostgreSQL, in your case the :: converts a date type of date, further, :: is represented as CAST(expression AS type).
Equally,
CAST (DATE_TRUNC('month', reg_date) AS DATE) AS delivr_month
What does "does not work" mean? Note that date_trunc in PostgreSQL returns a datetime. So if you need a date for your query to work, this is why you need ::date.

Bigquery Error code: Window ORDER BY expression references column start_date which is neither grouped nor aggregated at

I am using BigQuery for SQL and I can't figure out why there is an error message that comes like this:
Window ORDER BY expression references column start_date which is neither grouped nor aggregated at [4:73]
Here is my code:
SELECT EXTRACT(WEEK FROM start_date) as week, count(start_date) as count,
RANK() OVER (PARTITION BY start_station_name ORDER BY EXTRACT(WEEK FROM start_date))
from `bigquery-public-data.london_bicycles.cycle_hire`
GROUP BY EXTRACT(WEEK FROM start_date), start_station_name)
I thought I have grouped the week below, as seen in the last line. So what can cause this error message to keep popping up?
This is a parsing error in BigQuery, which you can work around with an aggregation function. Your query has another issue, which is the start_station_name.
SELECT EXTRACT(WEEK FROM start_date) as week, start_station_name, count(start_date) as count,
RANK() OVER (PARTITION BY start_station_name ORDER BY MIN(EXTRACT(WEEK FROM start_date)))
from `bigquery-public-data.london_bicycles.cycle_hire`
GROUP BY 1, 2;
The MIN() really serves no purpose other than lettering BigQuery parse the query. Because the expression is part of the GROUP BY, there is only one value for the MIN() to consider.
This is a bug in the BigQuery parsing, because it does not recognize that the expression is the same as the expression in the GROUP BY. Happily, it is easy to work around.
try like below using cte
with cte as
(
SELECT *, EXTRACT(WEEK FROM start_date) as week
from `bigquery-public-data.london_bicycles.cycle_hire`
) select week,count(start_date) as count,
RANK() OVER (PARTITION BY start_station_name ORDER BY week)
from cte group by week,start_station_name
In query you need to make sure that you have to put ORDER BY only on those values which you are selecting.
With your query, the problem is you are doing ORDER BY EXTRACT(WEEK from start_date). Rather than doing this you should write ORDER BY week because you are selecting week already

Cannot group by timestamp_trunc

I have this query in standard sql.
select timestamp_trunc(endTime, MONTH), count(1)
from `simple_table`
group by timestamp_trunc(endTime, MONTH);
Which returnts the following error:
SELECT list expression references column endTime which is neither grouped nor aggregated at [1:24]
However, the following code:
select timestamp_trunc(endTime, MONTH)
from `simple_table`
limit 10
Works perfectly. Is there some hidden reference about BigQuery's ability to do group by that I am missing?
just do as below
select timestamp_trunc(endTime, MONTH), count(1)
from `simple_table`
group by 1
or
select timestamp_trunc(endTime, MONTH) as m, count(1)
from `simple_table`
group by m
I think what happens is not the problem in using functions/expressions in GROUP BY, but rather the fact that engine does not recognize that expression for field in SELECT list and expression in GROUP BY are the same. Rather they are treated as different, thus engine think endTime filed is "orphan" (neither aggregated nor grouped by)
for example, below will work (of course it is not what you need - but it proves that group by accepts expressions)
select count(1)
from `simple_table`
group by timestamp_trunc(endTime, MONTH)

error: column "month" does not exist in PG query

My PG query:
SELECT "Tracks"."PageId",
date_trunc("month", "Tracks"."createdAt") AS month,
count(*)
FROM "Tracks"
WHERE "Tracks"."PageId" IN (29,30,31)
GROUP BY month, "Tracks"."PageId"
and my schema:
id, createdAt, updatedAt, PageId
A bit confused as to why I'm receiving this error!
You can use an alias in the where or group by clause. You need to repeat the expression:
SELECT "Tracks"."PageId",
date_trunc('month', "Tracks"."createdAt") AS month,
count(*)
FROM "Tracks"
WHERE "Tracks"."PageId" IN (29,30,31)
GROUP BY date_trunc('month', "Tracks"."createdAt"), "Tracks"."PageId";
Note that the first parameter for date_trunc() is a varchar value, so you need to put that in single quotes, not double quotes.
If you don't want to repeat the expression you can put that into a derived table:
select "PageId", month, count(*)
from (
SELECT "Tracks"."PageId",
date_trunc('month', "Tracks"."createdAt") AS month
FROM "Tracks"
WHERE "Tracks"."PageId" IN (29,30,31)
) t
group by month, "PageId";
Unrelated, but: you should really avoid quoted identifiers. They are much more trouble then they are worth it

DISTINCT date value in ORA-01791: not a SELECTed expression

I would like to get the unique date values from order table using oracle query. I am getting
ORA-01791: not a SELECTed expression
error, When i tried this below query
SELECT DISTINCT (TO_DATE(LAST_INSERT_TIMESTAMP, 'YYYY-MM-DD HH24:MI'))
FROM ORDER
WHERE LAST_INSERT_TIMESTAMP IS NOT NULL
ORDER BY LAST_INSERT_TIMESTAMP DESC;
LAST_INSERT_TIMESTAMP is not in your result list, because you have aggregated your rows with DISTINCT to a truncated timestamp. You can only order by this.
SELECT DISTINCT TRUNC(LAST_INSERT_TIMESTAMP, 'MI')
FROM ORDER
WHERE LAST_INSERT_TIMESTAMP IS NOT NULL
ORDER BY TRUNC(LAST_INSERT_TIMESTAMP, 'MI') DESC;
If you don't want to repeat the expression use positional sort:
ORDER BY 1 DESC;
Or use an alias for the expression:
SELECT DISTINCT TRUNC(LAST_INSERT_TIMESTAMP, 'MI') AS LAST_INSERT
FROM ORDER
WHERE LAST_INSERT_TIMESTAMP IS NOT NULL
ORDER BY LAST_INSERT DESC;
Please note that I replaced your TO_DATE with the appropriate TRUNC because all you want to do is truncate your timestamp, not convert to and from string.