Combining columns in a complex pivot - sql

I have this table:
INPUT
I wish to transform it into another table, that contains
The Date/Id/Order columns (primary key columns)
A TotalCount column, containing the value of the original table's Count column where all the Cond columns are NULL
One Count column for each CondX column, containing the value of the original table's Count column where CondX = 1 and the rest of the Cond = NULL
One Count column for each combination of non-null (Cond1 OR Cond2 OR Cond3) + (CondA OR CondB), containing the value of the original table's Count column where the two applicable Cond = 1 and the rest = NULL
Example:
So basically, I want my new table to have these columns:
Date, Id, Order, TotalCount
Cond1Count, Cond2Count, Cond3Count, CondACount, CondBCount
Cond1AndCondACount, Cond1AndCondBCount, Cond2AndCondACount, Cond2AndCondBCount...
From the sample image, we'd have these values in the end:
DESIRED OUTPUT
(note: CondBCount = 0 for Order = 2, missed it in the image edition)
I'd show some SQL if I had any, but I'm actually not quite sure where to start with this problem. I could naively do a bunch of different SELECT Count WHERE ..., but I'm wondering if there's a better solution.

Without your table structure. You can sum multiple columns with sum & values, even in combination with CASE
Example:
SELECT *
FROM (
SELECT Date, Id, [Order],
(SELECT SUM(v)
FROM (VALUES (ISNULL(Cond1,0)), (ISNULL(Cond2,0)),...) AS value(v)) Cond1ACount
FROM YourTable
) sub
GROUP BY Date, Id, [Order]

Related

How can I separate same column values to a variable based on value in another column?

suppose I Have below table
A
B
1
one
2
two
1
three
2
four
1
last
for value in A=1
then I need the output as one;three;last
how can I query this in Oracle's SQL?
If you care whether you get the string "one;three;last" or "three;one;last" or some other combination of the three values, you'd need some additional column to order the results by (a database table is inherently unordered). If there is an id column that you're not showing, for example, that could do that, you'd order by id in the listagg.
If you don't care what order the values appear in the result, you could do something like this
select listagg( b, ';' ) within group (order by a)
from your_table
where a = 1

Determine the number of times a null value occurs in column B for a distinct value in column A, SQL table

I have a SQL table with "name" as one column, date as another, and location as a third. The location column supports null values.
I am trying to write a query to determine the number of times a null value occurs in the location column for each distinct value in the name column.
Can someone please assist?
One method uses conditional aggregation:
select name, sum(case when location is null then 1 else 0 end)
from t
group by name;
Another method that involves slightly less typing is:
select name, count(*) - count(location)
from t
group by name;
use count along with filters, as you only requires Null occurrence
select name, count(*) occurances
from mytable
where location is null
group by name
From your question, you'll want to get a distinct list of all different 'name' rows, and then you would like a count of how many NULLs there are per each name.
The following will achieve this:
SELECT name, count(*) as null_counts
FROM table
WHERE location IS NULL
GROUP BY name
The WHERE clause will only retrieve records where the records have NULL as their location.
The GROUP BY will pivot the data based on NAME.
The SELECT will give you the name, and the COUNT(*) of the number of records, per name.

Converting multiple rows into single row with multiple columns

I have a table that has multiple rows for a distinct CARD_ID listing different roles assigned to that CARD_ID. I'd like to have a query that creates a single row for each distinct CARD_ID that has multiple columns listing the different roles. See image for example of current table. Duplicates are highlighted.
So, I'd like one row for CARD_IDs 1-10, with columns in each row for Cardholder, Reconciler, and Approver.
If a particular CARD_ID doesn't have one of those roles, I'm ok with that field being null or having some other type of indicator.
One method i conditional aggregation:
select card_id,
max(iif(role = 'Reconciler', col, NULL)) as reconciler_col,
max(iif(role = 'Approver', col, NULL)) as approver_col,
max(iif(role = 'Cardholder', col, NULL)) as cardholder_col
from t
group by card_id;
col is a column that you want to pivot. You can add more than one column, just by adding more max(iif . . .) to the select.

Taking out common data

I want to compare two column and take out the common rows which are present in table1 and table 2 from two different tables.
table 1 table 2 result
mobnum A mobnum B 988123456
988123456 988124567201718 988123457
988124567 988123456201718
944123456 988623456201718
I'm not quite sure since you haven't really formated your data in a nice way but I think the code below will give you what you want, I included the second table in the where () in order to only select matching values. If you need the rows simply change "Select Num" to Select the unique Id's and go from there.
Table Test_1:
Num
988123456
988124
988124567
944123456
Table Test_2:
Num
988123456
988123457
9881234
9886234
Query:
select Num from Test_1 where Num in (Select Num from Test_2)
Output:
Num
988123456

How to create an integer from a certain string cell in PSQL

I have three certain columns in a table I am trying to query, say ID(char), Amount(bigint) and Reference(char). Here is a sample of a few entries from this table. The first two rows have no entry in the third column.
ID | Amount | Reference
16266| 24000|
16267| -12500|
16268| 25000| abc:185729000003412
16269| 25000| abc:185730000003412
What I am trying to get is a query or a function that will return the ids of the duplicate rows that have the same amount and the same modulus (%100000000) of the number in the string in the reference column.
The only cells in the reference column I am interested in will all have 'abc:' before the whole number, and nothing after the number. I need some way to convert that final field (string) into a int so I can search for the modulus of that number
Here is the script I will run once I get the reference field converted into a number without the 'abc:'
CREATE TEMP TABLE tableA (
id int,
amount int,
referenceNo bigint)
INSERT INTO tableA (id, amount, referenceNo) SELECT id, net_amount, longnumber%100000000 AS referenceNo FROM deposit_item
SELECT DISTINCT * FROM tableA WHERE referenceNo > 1 AND amount > 1
Basically, how do I convert the reference field (abc:185729000003412) to an integer in PSQL (185729000003412 or 3412)?
Assuming that reference id is always delimited by :
split_part(Reference, ':', 2)::integer
should work.
Edit:
If you want to match abc: specifically - try this:
CASE
WHEN position('abc:' in Reference) > 0
THEN split_part(Reference, 'abc:', 2)::integer
ELSE 0
END
But you should indeed consider storing the xxx: prefix separately.