How i can write this query in PostgreSQL? - mysql

Original from MySQL. There I want to know how many separate rows with columns by condition:
SELECT
sum(status='waiting'),
sum(source='twitter'),
sum(no_send_before <= '2009-05-28 03:17:50'),
sum(tries <= 20),
count(*)
FROM table_name
*************************** 1. row ***************************
sum(status ='waiting'): 550
sum(source='twitter'): 37271
sum(no_send_before <= '2009-05-28 03:17:50'): 36975
sum(tries <= 20): 36569
count(*): 37271

For a query that is consistent between the two databases, use case:
SELECT sum(case when status='waiting' then 1 else 0 end),
sum(case when source='twitter' then 1 else 0 end),
sum(case when no_send_before <= '2009-05-28 03:17:50' then 1 else 0 end),
sum(case when tries <= 20 then 1 else 0 end),
count(*)
FROM table_name;
For a shorter, Postgres-specific syntax:
SELECT sum((status='waiting')::int),
sum((source='twitter')::int)),
sum((no_send_before <= '2009-05-28 03:17:50'))::int),
sum((tries <= 20))::int),
count(*)
FROM table_name

Related

Why are my various CASE WHEN functions returning the same values?

Im trying to write a query that returns a count depending on the value of a feedback field that ranges from 0-5 (0 meaning that it was not rated).
I want:
Count of all rows ( anything rated 1 or greater)
Count of all rows rated as 1 (anything = 1)
And all rows rated as 1 and also is the first iteration of a given task (anything rated =1 and iteration = 0)
I have written this query but I am getting the same value for all counts:
select
DATE_FORMAT(created_at,'%M') as Month,
COUNT(CASE WHEN rate > 0 THEN 1 ELSE 0 END) AS total,
COUNT(CASE WHEN rate = 1 THEN 1 ELSE 0 END) AS Rated_1,
COUNT(CASE WHEN client_feedback = 1 AND index = 0 THEN 1 ELSE 0 END) AS first_iteration_rated_1
from tablexxx
where created_at between date('2022-04-01') and date('2022-10-01')
GROUP BY Month
Try to use SUM() instead of COUNT().
Count() will count up regardless of the value being 0 or 1.
you can have two approaches:
method 1: use NULL in else part of the CASE
select
DATE_FORMAT(created_at,'%M') as Month,
COUNT(CASE WHEN rate > 0 THEN 1 ELSE null END) AS total,
COUNT(CASE WHEN rate = 1 THEN 1 ELSE null END) AS Rated_1,
COUNT(CASE WHEN client_feedback = 1 AND index = 0 THEN 1 ELSE null END) AS first_iteration_rated_1
from tablexxx
where created_at between date('2022-04-01') and date('2022-10-01')
GROUP BY Month
method 2: use sum instead of count
select
DATE_FORMAT(created_at,'%M') as Month,
SUM(CASE WHEN rate > 0 THEN 1 ELSE 0 END) AS total,
SUM(CASE WHEN rate = 1 THEN 1 ELSE 0 END) AS Rated_1,
SUM(CASE WHEN client_feedback = 1 AND index = 0 THEN 1 ELSE 0 END) AS first_iteration_rated_1
from tablexxx
where created_at between date('2022-04-01') and date('2022-10-01')
GROUP BY Month

Replacing UNION ALL to increase speed when summarizing multiple columns

I have a dataset with columns V1 V2 V3 V4 ... V200 where I would like to return a table with the column name and how many NULL, zero and below zero values each column has. My Current code looks like:
SELECT 'V1' AS column_name, SUM(CASE WHEN V1 IS NULL THEN 1 ELSE 0 END) AS n_null, SUM(...V1 = 0) AS n_zero, SUM(... V1 < 0) AS n_below_zero UNION ALL
...
SELECT 'V200' AS column_name, SUM(CASE WHEN V200 IS NULL THEN 1 ELSE 0 END) AS n_null, SUM(...V200 = 0) AS n_zero, SUM(... V200 < 0) AS n_below_zero
Is there a faster way than this? I feel that 200 UNION ALL is not the fastest way
I am running on Databricks, so Spark SQL.
It should be way faster to have one full table scan and aggregate all rows to one row containing all counts. Here is how to do that:
SELECT
SUM(CASE WHEN V1 IS NULL THEN 1 ELSE 0 END) AS v1_null_cnt,
SUM(CASE WHEN V1 = 0 THEN 1 ELSE 0 END) AS v1_zero_cnt,
SUM(CASE WHEN V1 < 0 THEN 1 ELSE 0 END) AS v1_nega_cnt,
SUM(CASE WHEN V2 IS NULL THEN 1 ELSE 0 END) AS v2_null_cnt,
SUM(CASE WHEN V2 = 0 THEN 1 ELSE 0 END) AS v2_zero_cnt,
SUM(CASE WHEN V2 < 0 THEN 1 ELSE 0 END) AS v2_nega_cnt,
...
SUM(CASE WHEN V200 < 0 THEN 1 ELSE 0 END) AS v200_nega_cnt
FROM mytable;
Once you have this result row, you can unpivot it to get one row per table column, if you prefer this.

How to get count of columns using single queries

I have a table in my database from which i want to fetch data on the basis of count
my table name is syncbill and columns are Cancelled and Noofprints i am trying to write a query to fetch the count of cancelled and count of noofbills using single query
For cancelled i want to fetch count of cancelled where cancelled<>Y
for Noofprints i want to fetch count of noofprints where noofprints>1
I am using
select count(CANCELLED) as canceledbill,count(NOOFPRINTS) as duplicatebill
from syncbill where CANCELLED<>'Y' and NOOFPRINTS>1`
this query but it is giving me the same no of counts for both
any one out-here please guide me
you can use sum() with case expreseeion
SELECT
sum(CASE WHEN CANCELLED <> 'Y' THEN 1 else 0 END) AS canceledbill,
sum(CASE WHEN NOOFPRINTS > 1 THEN 1 else 0 END) AS duplicatebill
FROM table_name;
Use conditional aggregation:
SELECT
COUNT(CASE WHEN CANCELLED <> 'Y' THEN 1 END) AS cancelledbill,
COUNT(CASE WHEN NOOFPRINTS > 1 THEN 1 END) AS duplicatebill
FROM yourTable;
If you are actually using MySQL, then the above can be simplified to this:
SELECT
SUM(CANCELLED <> 'Y') AS cancelledbill,
SUM(NOOFPRINTS > 1) AS duplicatebill
FROM yourTable;
USE CASE WHEN Expression
select
sum(case when CANCELLED <> 'Y' then 1 else 0 end) AS cancelledbill,
sum(case when NOOFPRINTS > 1 then 1 else 0 end) AS duplicatebill
FROM tablename;

SQL return having sum value

I have a query that checks a group and makes sure that it has more than 1 value under 2
SELECT `tile` FROM TFResults
GROUP BY `tile`
HAVING SUM(CASE WHEN `Place` < 2 THEN 1 ELSE 0 END)> 1 ;
I would like to return the value of sum also but can't seem to get it to work
SELECT `tile`, thesum
FROM TFResults
GROUP BY `tile`
HAVING SUM(CASE WHEN `Place` < 2 THEN 1 ELSE 0 END) as thesum > 1 ;
You define alias names in the select clause
SELECT tile,
SUM(CASE WHEN Place < 2 THEN 1 ELSE 0 END) as thesum
FROM TFResults
GROUP BY tile
HAVING thesum > 1
First you need to move sum part to select statement. And if you need only one column to check then use if instead CASE. Check Below
SELECT tile, SUM(if(Place < 2, 1, 0)) place_sum
FROM TFResults
GROUP BY tile
HAVING place_sum > 1
Just move sum statement to select:
SELECT
`tile`,
SUM(CASE WHEN `Place` < 2 THEN 1 ELSE 0 END) AS thesum
FROM TFResults
GROUP BY `tile`
HAVING thesum > 1 ;

mysql show 0 if selected value is null?

I have a long sql query that calculates a few things about payments and shipments. In some cases the value is null. I think that's because there's being divided by 0.
Here's a small part of my query:
ROUND(sum(case when shipping_method = 'c' AND (paid_amount - shipping_costs) < 70 then 1 end) * 100 / sum(case when shipping_method = 'c' then 1 end),2) as co_less_70,
I think that when this part is 0: sum(case when shipping_method = 'colissimo' then 1 end),2) my query shows null. Is there any way to assign a default value for this co_less_70 column?
Yes. You can use the COALESCE() function:
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce
Returns the first non-NULL value in the list, or NULL if there are no non-NULL values.
In your code:
COALESCE(
ROUND(sum(case when shipping_method = 'c' AND (paid_amount - shipping_costs) < 70 then 1 end) * 100 / sum(case when shipping_method = 'c' then 1 end),2),
0
) AS co_less_70
IFNULL(
ROUND(sum(case when shipping_method = 'c' AND (paid_amount - shipping_costs) < 70 then 1 end) * 100 / sum(case when shipping_method = 'c' then 1 end),2)
,<default>) AS co_less_70,
You can set a default case, but anything except zero :-
sum(case when shipping_method = 'colissimo' then 1 else some_value end case),2)