postgres 9.2 counting the number of statuses by ordinal - sql

suppose i have this result set:
Location|Company|Account Number|First Check Date|First Status|Second Check Date|Second Status|Third Check Date|Third Status|Fourth Check Date|Fourth Status|Fifth Check Date|Fifth Status
Westeros|Acme Corp.|1014541|8/23/2018|Denied||||||||
Westeros|Acme Corp.|1014544|8/23/2018|Pending||||||||
Westeros|Acme Corp.|1014561|8/23/2018|Pending||||||||
Westeros|Sirius Cybernetics Corp|1014562|8/22/2018|Finalized||||||||
Westeros|Sirius Cybernetics Corp|1014573|8/23/2018|Pending||||||||
Westeros|MomCorp|1014579|8/22/2018|Denied||||||||
Dorne|MomCorp|1018984|8/20/2018|Pending||||||||
Dorne|Sirius Cybernetics Corp|1019017|8/22/2018|Pending||||||||
The North|MomCorp|1033591|8/16/2018|Pending||||||||
The North|MomCorp|1033910|8/16/2018|Not Found||||||||
The North|Amerigroup|1033964|8/16/2018|Partial Payment||||||||
The North|MomCorp|1034036|8/22/2018|Paid||||||||
The North|MomCorp|1034041|8/23/2018|Partial Payment||||||||
Iron Islands|AG White|1175033|8/22/2018|Pending||||||||
Stormlands|foobar|1220179|8/14/2018|Not Found|8/21/2018|Not Found||||||
which is returnd from a query that can be boiled down to
select Location,Company,Account Number,First Check Date,First Status,Second Check Date,Second Status,Third Check Date,Third Status,Fourth Check Date,Fourth Status,Fifth Check Date,Fifth Status
from subselect as results
what i an trying to do is generate a count of elements in each status column.
for example the first status count would be 15, the second would be 1 and the rest are 0.
I have tried doing this with over() and using a sum(case when 'first_status' then1 else 0 end) but nothing seems to give correct results.
any suggestions on how to accomplish this?

Assuming the missing values are NULL, you can do:
select r.*,
count(status1) over () as status1_cnt,
count(status2) over () as status2_cnt,
. . .
from subselect as results
However, the empty statuses might be something else, such as ''. If so, a simple approach is:
select r.*,
count(nullif(status1, '')) over () as status1_cnt,
count(nullif(status2, '')) over () as status2_cnt,
. . .
from subselect as results

Related

SQL: delete only if subquery (containing 0, 1, or more rows) equals scalar value

Description
I'm trying to do something like:
DELETE FROM ...
-- `<my_id>` is any given long scalar value
WHERE <my_id> = (SELECT id FROM ... WHERE ...);
That syntax is not entirely correct. If the select subquery contains more than one row, then we get an error like:
Scalar subquery contains more than one row
However, my intended purpose is indeed:
if the subquery returns exactly 1 value equal to the scalar value (<my_id>) ==> delete
else (0, or 2 or more values, or 1 non-equal value) ==> do not delete (ignore)
Question
I do not want neither IN nor EXISTS. I need rather something like "equals", which can compare a scalar value against possibly multi-valued rows.
What is the syntax in SQL for that?
Stack
In particular, I'm testing this with H2.
One method is:
DELETE FROM ...
WHERE <my_id> IN (SELECT id FROM ... WHERE ...) AND
(SELECT COUNT(*) FROM . . . WHERE . . .) = 1;
However, this is more simply written as:
DELETE FROM ...
WHERE <my_id> = (SELECT MAX(id)
FROM . . .
WHERE . .
HAVING COUNT(*) = 1
) ;
If the count is not 1, then the subquery returns nothing and there is no match (so nothing is deleted).

Query with number after GROUP BY

I have a query to get data like this : .....
WHERE ((column1=1 OR column1=3) AND
(column2= 0 or column2= 4)
) AND (1)
GROUP BY 1,(2)
I don't know the meaning of "AND (1) GROUP BY 1,(2)" does anyone can explain it? , thank you
Let's format the query a little, that should help clear it up:
WHERE ((column1=1 OR column1=3)
AND (column2= 0 or column2= 4) )
AND (1)
GROUP BY 1,(2)
So the AND (1) part is the same as saying AND (true) or AND (1=1). It always returns true so is effectively doing nothing.
The GROUP BY is just using the column position of your SELECT. So it's grouping byt the first column, then the second.

num_rows in postgres always return 1

I'm trying to do a SELECT COUNT(*) with Postgres.
What I need: Catch the rows affected by the query. It's a school system. If the student is not registered, do something (if).
What I tried:
$query = pg_query("SELECT COUNT(*) FROM inscritossimulado
WHERE codigo_da_escola = '".$CodEscola."'
AND codigo_do_simulado = '".$simulado."'
AND codigo_do_aluno = '".$aluno."'");
if(pg_num_rows($query) == 0)
{
echo "Error you're not registered!";
}
else
{
echo "Hello!";
}
Note: The student in question IS NOT REGISTERED, but the result is always 1 and not 0.
For some reason, when I "show" the query, the result is: "Resource id #21". But, I look many times in the table, and the user is not there.
You are counting the number of rows in the answer, and your query always returns a single line.
Your query says: return one row giving the number of students matching my criteria. If no one matches, you will get back one row with the value 0. If you have 7 people matching, you will get back one row with the value 7.
If you change your query to select * from ... you will get the right answer from pg_num_rows().
Actually, don't count at all. You don't need the count. Just check for existence, which is proven if a single row qualifies:
$query = pg_query(
'SELECT 1
FROM inscritossimulado
WHERE codigo_da_escola = $$' . $CodEscola . '$$
AND codigo_do_simulado = $$' . $simulado. '$$
AND codigo_do_aluno = $$' . $aluno . '$$
LIMIT 1');
Returns 1 row if found, else no row.
Using dollar-quoting in the SQL code, so we can use the safer and faster single quotes in PHP (I presume).
The problem with the aggregate function count() (besides being more expensive) is that it always returns a row - with the value 0 if no rows qualify.
But this still stinks. Don't use string concatenation, which is an open invitation for SQL injection. Rather use prepared statements ... Check out PDO ...

Build a field in the Select Q

I am trying to add a field in my Select statment that will create a field with my desired output or make the field results empty. My Boss doesn't want to scan the entire mopdescription field if they have to.
Please see code ** to see if you can make sense of this question/request.
SELECT MOPACTIVITY.MOPID,
**UPPER(MOPACTIVITY.MOPDESCRIPTION) LIKE '%FTTT%'
OR UPPER(MOPACTIVITY.MOPDESCRIPTION) LIKE '%VZW%' AS "NOTE_DISP"**,
MOPACTIVITY.MOPDESCRIPTION
FROM MOPUSER.MOPACTIVITY
SELECT mopid
, CASE
WHEN INSTR(UPPER(mopdescription), 'FTTT') > 0
THEN SUBSTR(mopdescription, INSTR(UPPER(mopdescription), 'FTTT'))
WHEN INSTR(UPPER(mopdescription), 'VZW') > 0
THEN SUBSTR(mopdescription, INSTR(UPPER(mopdescription), 'VZW'))
ELSE NULL
END AS note_disp
FROM mopuser.mopactivity';

Return 0 if field is null in MySQL

In MySQL, is there a way to set the "total" fields to zero if they are NULL?
Here is what I have:
SELECT uo.order_id, uo.order_total, uo.order_status,
(SELECT SUM(uop.price * uop.qty)
FROM uc_order_products uop
WHERE uo.order_id = uop.order_id
) AS products_subtotal,
(SELECT SUM(upr.amount)
FROM uc_payment_receipts upr
WHERE uo.order_id = upr.order_id
) AS payment_received,
(SELECT SUM(uoli.amount)
FROM uc_order_line_items uoli
WHERE uo.order_id = uoli.order_id
) AS line_item_subtotal
FROM uc_orders uo
WHERE uo.order_status NOT IN ("future", "canceled")
AND uo.uid = 4172;
The data comes out fine, except the NULL fields should be 0.
How can I return 0 for NULL in MySQL?
Use IFNULL:
IFNULL(expr1, 0)
From the documentation:
If expr1 is not NULL, IFNULL() returns expr1; otherwise it returns expr2. IFNULL() returns a numeric or string value, depending on the context in which it is used.
You can use coalesce(column_name,0) instead of just column_name. The coalesce function returns the first non-NULL value in the list.
I should mention that per-row functions like this are usually problematic for scalability. If you think your database may get to be a decent size, it's often better to use extra columns and triggers to move the cost from the select to the insert/update.
This amortises the cost assuming your database is read more often than written (and most of them are).
None of the above answers were complete for me.
If your field is named field, so the selector should be the following one:
IFNULL(`field`,0) AS field
For example in a SELECT query:
SELECT IFNULL(`field`,0) AS field, `otherfield` FROM `mytable`
Hope this can help someone to not waste time.
You can try something like this
IFNULL(NULLIF(X, '' ), 0)
Attribute X is assumed to be empty if it is an empty String, so after that you can declare as a zero instead of last value. In another case, it would remain its original value.
Anyway, just to give another way to do that.
Yes IFNULL function will be working to achieve your desired result.
SELECT uo.order_id, uo.order_total, uo.order_status,
(SELECT IFNULL(SUM(uop.price * uop.qty),0)
FROM uc_order_products uop
WHERE uo.order_id = uop.order_id
) AS products_subtotal,
(SELECT IFNULL(SUM(upr.amount),0)
FROM uc_payment_receipts upr
WHERE uo.order_id = upr.order_id
) AS payment_received,
(SELECT IFNULL(SUM(uoli.amount),0)
FROM uc_order_line_items uoli
WHERE uo.order_id = uoli.order_id
) AS line_item_subtotal
FROM uc_orders uo
WHERE uo.order_status NOT IN ("future", "canceled")
AND uo.uid = 4172;