PLSQL group by with range table joining is showing proper count - date

Hi I am joining a table with range of 1 month days, to get the per day count based of join table(base table).
For that I using left outer join to get count of per day.
where my base table is as shown below (table name REGISTRIERUNG]
And I have create range of one month using below query
SELECT TO_DATE ('01-10-2017', 'dd-mm-yyyy') + ROWNUM - 1 AS daterange
FROM all_objects
WHERE ROWNUM <=
TO_DATE ('30-10-2017', 'dd-mm-yyyy')
- TO_DATE ('01-10-2017', 'dd-mm-yyyy')
+ 1;
but I getting count 1 for date where there now record matching with range table
instead of 0 count.
I am using below query for final result.
SELECT TRUNC (a.daterange), COUNT (a.daterange)
FROM (SELECT TO_DATE ('01-10-2017', 'dd-mm-yyyy') + ROWNUM - 1
AS daterange
FROM all_objects
WHERE ROWNUM <=
TO_DATE ('30-10-2017', 'dd-mm-yyyy')
- TO_DATE ('01-10-2017', 'dd-mm-yyyy')
+ 1) a
LEFT OUTER JOIN
REGISTRIERUNG b
ON TRUNC (a.daterange) = TRUNC (b.MODIFIKATIONZEIT)
GROUP BY TRUNC (a.daterange)
ORDER BY TRUNC (a.daterange) ASC;

You should not count rows based on the column that is always populated (in your query a.daterange is always populated because this column from your inline view has all the dates in a month). Rather, you should count number of rows from the table that is outer-joined to the inline view with generated dates. Note that count function will not take into account rows that have null value in the column modifikationzeit.
For instance:
select a.daterange,
count(b.modifikationzeit)
from (select to_date('01-10-2017', 'dd-mm-yyyy') + level - 1 as daterange
from dual
connect by level <= to_date('31-10-2017', 'dd-mm-yyyy') -
to_date('01-10-2017', 'dd-mm-yyyy') + 1) a
left outer join registrierung b
on a.daterange = trunc(b.modifikationzeit)
group by a.daterange
order by a.daterange;
I have removed unnecessary trunc's, and converted query from all_objects to the one that uses connect by clause. I also fixed date generation for October - it has 31 days, not 30 as per your example.

Related

How to get sum of int and 0 as missing with date in sql query?

I have the following query and I would like to add all the views of a specific date and if there is no view, I would like to get date and sum as 0 as shown below.
SELECT SUM("videoView"."views"), "videoView"."startDate"::timestamp::date
FROM "videoView"
WHERE "videoView"."videoId" =23
AND "videoView"."views"
BETWEEN = '2021/11/25' AND '2021/11/28'
GROUP BY "videoView"."startDate"::timestamp::date
The result I want is:
sum date
3 2021/11/25
0 2021/11/26
0 2021/11/27
4 2021/11/28
The result i am getting is
sum date
3 2021/11/25
4 2021/11/28
You need a calendar table here which holds all the dates which you want to appear in the report. The need for this table is that your current data set may be entirely missing certain dates for which there simply isn't any data. Consider:
WITH dates AS (
SELECT '2021-11-25'::date AS dt UNION ALL
SELECT '2021-11-26'::date UNION ALL
SELECT '2021-11-27'::date UNION ALL
SELECT '2021-11-28'::date
)
SELECT d.dt, COALESCE(SUM(v.views), 0) AS numViews
FROM dates d
LEFT JOIN videoView v
ON v.startDate = d.dt AND
v.videoId = 23
WHERE
d.dt BETWEEN '2021-11-25'::date AND '2021-11-28'::date
GROUP BY d.dt
ORDER BY d.dt;

How to fix column "sv.last_updated" must appear in the GROUP BY clause or be used in an aggregate function in PostgreSQL

What I'm trying to achieve is like get the total count of transactions and their total amount for every hour a given day.
I have written a cast query in PostgreSQL. if I execute it gives
column "sv.last_updated" must appear in the GROUP BY clause or be used in an aggregate function
select cast('00:00' as time) + g.h * interval '1 hour' as time,
count(sv.id) as counts,
sum(sv.amount) as amount
from generate_series(0, 23, 1) g(h)
left join paymentvirtualization.summery_virtualizer sv
on extract(hour from sv.last_updated) = g.h
and date_trunc('day', sv.last_updated) = '2021-09-28'
and sv.guid = '1aecb2ba5c3941fe9cdab0cbf0c64937'
group by g.h
order by g.h,sv.last_updated desc limit 1;
What is this issue and how can i fix this?
Thanks.

T-SQL apply where clause to function fields not working

I'm having a hard time filtering this view by CreateDate. The CreateDate in the table is in the following format: 2013-10-14 15:53:33.900
I managed to DATEPART the year month and day into separate columns, but now it's not letting me use my WHERE clause on those newly created columns. Specifically, the error is "Invalid Column Name CreateYear" for both lines. What am I doing wrong here guys? Is there a better/easier way to do this than parse out the day, month, and year? It seems overkill. I've spent quite a bit of hours on this to no avail.
SELECT convert(varchar, DATEPART(month,v.CreateDate)) CreateMonth,
convert(varchar, DATEPART(DAY,v.CreateDate)) CreateDay,
convert(varchar, DATEPART(YEAR,v.CreateDate)) CreateYear,
v.CreateDate,
v.customerName
From
vw_Name_SQL_DailyPartsUsage v
full outer join
ABC.serviceteamstechnicians t on v.TechnicianNumber = t.AgentNumber
full outer join
ABC.ServiceTeams s on t.STID = s.STID
where
CreateYear >= '02/01/2018'
and
CreateYear <= '02/20/2018'
You cannot reference an alias from the select in the where
Even if you could why would you expect year to be '02/01/2018'
Why are you converting to varchar
where year(v.CreateDate) = 2018
or
select crdate, cast(crdate as date), year(crdate), month(crdate), day(crdate)
from sysObjects
where cast(crdate as date) <= '2014-2-20'
and cast(crdate as date) >= '2000-2-10'
order by crdate
You could use:
SELECT convert(varchar, DATEPART(month,v.CreateDate)) CreateMonth,
convert(varchar, DATEPART(DAY,v.CreateDate)) CreateDay,
convert(varchar, DATEPART(YEAR,v.CreateDate)) CreateYear,
v.CreateDate,
v.customerName
From vw_Name_SQL_DailyPartsUsage v
full outer join
ABC.serviceteamstechnicians t on v.TechnicianNumber = t.AgentNumber
full outer join
ABC.ServiceTeams s on t.STID = s.STID
where CreateDate BETWEEN '20180102' and '20180220';
More info about the logical query processing is that you cannot refer to a column alias at SELECT in the WHERE clause without using a subquery/CROSS APPLY.

Include value from cte when it has not match

In my table I have some entries which - by the table's date column - is not older than 2016-01-04 (January 4, 2016).
Now I would like to make a query which more or less counts the number of rows which have a specific date value, but I'd like this query to be able to return a 0 count for dates not present in table.
I have this:
with date_count as (select '2016-01-01'::date + CAST(offs || ' days' as
interval) as date from generate_series(0, 6, 1) AS offs ) select
date_count.date, count(allocation_id) as packs_used from medicine_allocation,
date_count where site_id = 1 and allocation_id is not null and timestamp
between date_count.date and date_count.date + interval '1 days' group by
date_count.date order by date_count.date;
This surely gives me a nice aggregated view of the date in my table, but since no rows are from before January 4 2016, they don't show in the result:
"2016-01-04 00:00:00";1
"2016-01-05 00:00:00";2
"2016-01-06 00:00:00";4
"2016-01-07 00:00:00";3
I would like this:
"2016-01-01 00:00:00";0
"2016-01-02 00:00:00";0
"2016-01-03 00:00:00";0
"2016-01-04 00:00:00";1
"2016-01-05 00:00:00";2
"2016-01-06 00:00:00";4
"2016-01-07 00:00:00";3
I have also tried right join on the cte, but this yields the same result. I cannot quite grasp how to do this... any help out there?
Best,
Janus
You simply need a left join:
with date_count as (
select '2016-01-01'::date + CAST(offs || ' days' as
interval) as date
from generate_series(0, 6, 1) AS offs
)
select dc.date, count(ma.allocation_id) as packs_used
from date_count dc left join
medicine_allocation ma
on ma.site_id = 1 and ma.allocation_id is not null and
ma.timestamp between dc.date and dc.date + interval '1 days'
group by dc.date
order by dc.date;
A word of advice: Never use commas in the FROM clause. Always use explicit JOIN syntax.
You will also notice that the where conditions were moved to the ON clause. That is necessary because they are on the second table.

Creating 'Empty' Records for Days of the Month Without Records

I have a very simpl postgres (9.3) query that looks like this:
SELECT a.date, b.status
FROM sis.table_a a
JOIN sis.table_b b ON a.thing_id = b.thing_id
WHERE EXTRACT(MONTH FROM a.date) = 06
AND EXTRACT(YEAR FROM a.date) = 2015
Some days of the month of June do not exist in table_a and thus are obviously not joined to table_b. What is the best way to create records for these not represented days and assign a placeholder (e.g. 'EMPTY') to their 'status' column? Is this even possible to do using pure SQL?
Basically, you need LEFT JOIN and it looks like you also need generate_series() to provide the full set of days:
SELECT d.date
, a.date IS NOT NULL AS a_exists
, COALESCE(b.status, 'status_missing') AS status
FROM (
SELECT date::date
FROM generate_series('2015-06-01'::date
, '2015-06-30'::date
, interval '1 day') date
) d
LEFT JOIN sis.table_a a USING (date)
LEFT JOIN sis.table_b b USING (thing_id)
ORDER BY 1;
Use sargable WHERE conditions. What you had cannot use a plain index on date and has to default to a much more expensive sequential scan. (There are no more WHERE conditions in my final query.)
Aside: don't use the basic type name (and reserved word in standard SQL) date as identifier.
Related (2nd chapter):
PostgreSQL: running count of rows for a query 'by minute'