PGSQL: SORT isnt executed with rollup having only one result - sql

I'm having this code:
SELECT "monat",
CASE
WHEN count("erstkontakt_reaktionsdauer") < 3
THEN null
ELSE round(round(count("erstkontakt_reaktionsdauer"),2) / nullif(count("erstkontakt_reaktionsdauer"),0), 4)
END,
count("erstkontakt_reaktionsdauer")
FROM "schema"."tablename"
WHERE "monat" IN ('2021-04-01')
AND "monat" IS NOT NULL
GROUP BY rollup(1 )
HAVING count(*) >= 1
ORDER BY 1 NULLS FIRST
While this worked all along, When I have more than one month in
WHERE "monat" IN ('2021-04-01')
When I have only one inside the WHERE, the ROLLUP NULL isnt coming first

Using a temporary table works
SELECT * FROM (
SELECT "monat", CASE WHEN count("erstkontakt_reaktionsdauer") < 3 THEN null ELSE round(round(count("erstkontakt_reaktionsdauer"),2) / nullif(count("erstkontakt_reaktionsdauer"),0), 4) END, count("erstkontakt_reaktionsdauer") FROM "schema"."table" WHERE "monat" IN ('2021-03-01') AND "monat" IS NOT NULL GROUP BY rollup(1 ) HAVING count(*) >= 1
) t ORDER BY 1 NULLS FIRST
The Problem is, when there is only one result of the query (Rollup isnt counted), the SORT method isnt called. Using a temporary table solves this.

Related

Remove the duplicate rows based on Presence of Number of NULL values in a row

I was able to remove the duplicate rows, but I would like to remove the duplicate rows based on one more constraint. I want to keep only a row with a smaller number of NULL values.
Original Table
Ran the SQL Server Query
WITH CTE AS(
SELECT *,
RN = ROW_NUMBER()OVER(PARTITION BY Premise_ID ORDER BY Premise_ID)
FROM sde.Premise_Test
)
DELETE FROM CTE WHERE RN > 1
Result:
But I want to get this result
I have modified the SQL script as per the comment from Aaron. but the result is still the same. DB fiddle is showing NULL from IS NULL getting highlighted.
Update the ROW_NUMBER() function like this (no, there is no shorter way):
RN = ROW_NUMBER() OVER (
PARTITION BY Premise_ID
ORDER BY Premise_ID,
CASE WHEN Division IS NULL THEN 1 ELSE 0 END
+ CASE WHEN InstallationType IS NULL THEN 1 ELSE 0 END
+ CASE WHEN OtherColumn IS NULL THEN 1 ELSE 0 END
...
)

SQL Query problem (2 different order by) in 1 table

This is the original table:
I have 2 different query and I want to make 1 query for these:
SELECT *
FROM SAMPLE
WHERE ORDER_PRIORITY<40
ORDER BY FS_GENERATE_DATE IS NOT NULL, FS_GENERATE_DATE,ORDER_PRIORITY,CREATE_ID,CR_DATE,ORDER_QTY;
second:
SELECT *
FROM SAMPLE
WHERE ORDER_PRIORITY>=40
ORDER BY FS_GENERATE_DATE IS NOT NULL, FS_GENERATE_DATE,ORDER_PRIORITY,CREATE_ID,CR_DATE,ORDER_QTY;
I need the next result in only 1 query:
if the order_priority<40 than the order will be the first according to the order by
but if order_priority>=40 than these data will be after the lower priority (first conditional /op<40/).
Result:
You can add this to your order by clause:
case when ORDER_PRIORITY<40 then 0 else 1 end
The final query will be:
SELECT
*
FROM SAMPLE
WHERE ORDER_PRIORITY>=40
ORDER BY
case when ORDER_PRIORITY<40 then 0 else 1 end,
FS_GENERATE_DATE IS NOT NULL, FS_GENERATE_DATE,ORDER_PRIORITY,CREATE_ID,CR_DATE,ORDER_QTY;
You are clearly using a database where booleans are allowed in the ORDER BY. So, you can just use:
SELECT S.*
FROM SAMPLE S
ORDER BY (ORDER_PRIORITY < 40) DESC,
FS_GENERATE_DATE IS NOT NULL,
FS_GENERATE_DATE,
ORDER_PRIORITY,
CREATE_ID, CR_DATE, ORDER_QTY;

Create a new table with columns with case statements and max function

I have some problems in creating a new table from an old one with new columns defined by case statements.
I need to add to a new table three columns, where I compute the maximum based on different conditions. Specifically,
if time is between 1 and 3, I define a variable max_var_1_3 as max((-1)*var),
if time is between 1 and 6, I define a variable max_var_1_6 as max((-1)*var),
if time is between 1 and 12, I define a variable max_var_1_12 as max((-1)*var),
The max function needs to take the maximum value of the variable var in the window between 1 and 3, 1 and 6, 1 and 12 respectively.
I wrote this
create table new as(
select t1.*,
(case when time between 1 and 3 then MAX((-1)*var)
else var
end) as max_var_1_3,
(case when time between 1 and 6 then MAX((-1)*var)
else var
end) as max_var_1_6,
(case when time between 1 and 12 then MAX((-1)*var)
else var
end) as max_var_1_12
from old_table t1
group by time
) with data primary index time
but unfortunately it is not working. The old_table has already some columns, and I would like to import all of them and then compare the old table with the new one. I got an error that says that should be something between ) and ',', but I cannot understand what. I am using Teradata SQL.
Could you please help me?
Many thanks
The problem is that you have GROUP BY time in your query while trying to return all the other values with your SELECT t1.*. To make your query work as-is, you'd need to add each column from t1.* to your GROUP BY clause.
If you want to find the MAX value within the different time ranges AND also return all the rows, then you can use a window function. Something like this:
CREATE TABLE new AS (
SELECT
t1.*,
CASE
WHEN t1.time BETWEEN 1 AND 3 THEN (
MAX(CASE WHEN t1.time BETWEEN 1 AND 3 THEN (-1 * t1.var) ELSE NULL END) OVER()
)
ELSE t1.var
END AS max_var_1_3,
CASE
WHEN t1.time BETWEEN 1 AND 6 THEN (
MAX(CASE WHEN t1.time BETWEEN 1 AND 6 THEN (-1 * t1.var) ELSE NULL END) OVER()
)
ELSE t1.var
END AS max_var_1_6,
CASE
WHEN t1.time BETWEEN 1 AND 12 THEN (
MAX(CASE WHEN t1.time BETWEEN 1 AND 12 THEN (-1 * t1.var) ELSE NULL END) OVER()
)
ELSE t1.var
END AS max_var_1_12,
FROM old_table t1
) WITH DATA PRIMARY INDEX (time)
;
Here's the logic:
check if a row falls in the range
if it does, return the desired MAX value for rows in that range
otherwise, just return that given row's default value (var)
return all rows along with the three new columns
If you have performance issues, you could also move the max_var calculations to a CTE, since they only need to be calculated once. Also to avoid confusion, you may want to explicitly specify the values in your SELECT instead of using t1.*.
I don't have a TD system to test, but try it out and see if that works.
I cannot help with the CREATE TABLE AS, but the query you want is this:
SELECT
t.*,
(SELECT MAX(-1 * var) FROM old_table WHERE time BETWEEN 1 AND 3) AS max_var_1_3,
(SELECT MAX(-1 * var) FROM old_table WHERE time BETWEEN 1 AND 6) AS max_var_1_6,
(SELECT MAX(-1 * var) FROM old_table WHERE time BETWEEN 1 AND 12) AS max_var_1_12
FROM old_table t;

Sum distinct records in a table with duplicates in Teradata

I have a table that has some duplicates. I can count the distinct records to get the Total Volume. When I try to Sum when the CompTia Code is B92 and run distinct is still counts the dupes.
Here is the query:
select
a.repair_week_period,
count(distinct a.notif_id) as Total_Volume,
sum(distinct case when a.header_comptia_cd = 'B92' then 1 else 0 end) as B92_Sum
FROM artemis_biz_app.aca_service_event a
where a.Sales_Org_Cd = '8210'
and a.notif_creation_dt >= current_date - 180
group by 1
order by 1
;
Is There a way to only SUM the distinct records for B92?
I also tried inner joining the table on itself by selecting the distinct notification id and joining on that notification id, but still getting wrong sum counts.
Thanks!
Your B92_Sum currently returns either NULL, 1 or 2, this is definitely no sum.
To sum distinct values you need something like
sum(distinct case when a.header_comptia_cd = 'B92' then column_to_sum else 0 end)
If this column_to_sum is actually the notif_id you get a conditional count but not a sum.
Otherwise the distinct might remove too many vales and then you probably need a Derived Table where you remove duplicates before aggregation:
select
repair_week_period,
--no more distinct needed
count(a.notif_id) as Total_Volume,
sum(case when a.header_comptia_cd = 'B92' then column_to_sum else 0 end) as B92_Sum
FROM
(
select repair_week_period,
notif_id
header_comptia_cd,
column_to_sum
from artemis_biz_app.aca_service_event
where a.Sales_Org_Cd = '8210'
and a.notif_creation_dt >= current_date - 180
-- only onw row per notif_id
qualify row_number() over (partition by notif_id order by ???) = 1
) a
group by 1
order by 1
;
#dnoeth It seems the solution to my problem was not to SUM the data, but to count distinct it.
This is how I resolved my problem:
count(distinct case when a.header_comptia_cd = 'B92' then a.notif_id else NULL end) as B92_Sum

Null value in order by clause

I have a weird scenario, in which I need to keep all the rows at top in which X column has NULL value else sort by Y column. Can you help me in writing query.
ORDER BY CASE WHEN X IS NULL THEN 0 ELSE 1 END, Y
You can use a CASE statement in ORDER BY:
ORDER BY
CASE WHEN X IS NULL THEN 0 ELSE 1 END ASC, Y
Here you go, this will work with any sql platform -- for a specific platform there might be a better way to do it.
SELECT * FROM
(
SELECT 1 AS orderC, *
FROM tableName
WHERE Xcolumn is null
UNION ALL
SELECT 2 AS orderC, *
FROM tableName
WHERE Xcolumn is not null
)
ORDER BY orderC ASC, columnY
Note, if you don't want orderC to be in the output, just specify all the other columns in the outer select.
Sharing what I learned before using:
ORDER BY FIELD(Xcolumn, NULL) DESC, Ycolumn DESC
SELECT * FROM TABLENAME ORDER BY X ,Y
You can use query like below:
SELECT * FROM Emp WHERE empId= 6 AND DELETED = 0
ORDER BY CASE WHEN DOB IS NULL THEN 0 ELSE 1 END
, CREATETIMESTAMP.
for more details you can see here