Transpose partially using SQL [duplicate] - sql

This question already has answers here:
SQL Server dynamic PIVOT query?
(9 answers)
Closed 3 years ago.
I would like to do a transposition to create columns from long list.
Here is the example
+-------+--------+--------+-------+
| id | typeid | type | value |
+-------+--------+--------+-------+
| a0001 | 01 | sales | 10 |
| a0001 | 02 | revune | 3 |
| a0001 | 03 | asset | 6 |
| a0002 | 01 | sales | 8 |
| a0002 | 03 | asset | 2 |
| a0003 | 01 | sales | 12 |
| a0003 | 02 | revune | 8 |
| a0003 | 03 | asset | 8 |
+-------+--------+--------+-------+
Since the value in type is enumerable, I would like to transform it into separate columns.
Here is the one I expected:
+-------+-------+---------+-------+
| id | sales | revenue | asset |
+-------+-------+---------+-------+
| a0001 | 10 | 3 | 6 |
| a0002 | 8 | null | 2 |
| a0003 | 12 | 8 | 8 |
+-------+-------+---------+-------+
I know how to do it in py/js.
I would like to know if it is possible to transpose using SQL in the database query?

If you know exactly which columns you want, you can use conditional aggregation:
select id,
sum(case when type = 'sales' then value end) as sales,
sum(case when type = 'revenue' then value end) as revenue,
sum(case when type = 'assets' then value end) as assets
from t
group by id;
If you want this to be flexible, then you need to construct the SQL as a string and execute it. That is called dynamic SQL and depends very much on the database you are using.

You could use conditional aggregation
select a.id
, sum(case when typeid='01' then value else 0 end) sales
, sum(case when typeid='02' then value else 0 end) revenue
, sum(case when typeid='03' then value else 0 end) asset
from my_table
group by id

Related

Query in Oracle between time periods [duplicate]

This question already has answers here:
Dynamic Pivot in Oracle's SQL
(10 answers)
Closed 2 years ago.
I have the following question, when I make a query, how can I return the sums in different columns in various periods of time, for example I have this table:
---------------------------
| PRODUCT | VALUE | MONTH |
---------------------------
| P1 | 10 | 2 |
| P1 | 5 | 3 |
| P1 | 22 | 4 |
| P1 | 4 | 2 |
| P2 | 4 | 2 |
| P2 | 7 | 4 |
| P2 | 10 | 4 |
And I wish I had this result
--------------------------------------
| PRODUCT | MONTH2 | MONTH3 | MONTH4 |
--------------------------------------
| P1 | 14 | 5 | 22 |
| P2 | 4 | 0 | 17 |
You can use conditional aggregation:
select product,
sum(case when month = 2 then value end) as month2,
sum(case when month = 3 then value end) as month3,
sum(case when month = 4 then value end) as month4
from t
group by product;

Create a temp table with multiple conditions

I'm struggling with creating a temporary table with multiple conditions.
Let's call this main table A. I want to pull data from this table to output the distinct account with their last purchase date and payment date to a temporary table.
+---+--------+-----------+----------+
| | Acct | Trans_Date|Trans_code|
+---+--------+-----------+----------+
| 1 | ABC | July 31 | Purchase |
| 2 | ABC | Nov 5 | Payment |
| 3 | DEF | Mar 1 | Purchase |
| 4 | ABC | June 5 | Purchase |
| 5 | GFH | Feb 7 | Payment |
| 6 | GFH | Mar 9 | Purchase |
| 7 | DEF | Aug 8 | Payment |
| 8 | GFH | Mar 9 | Purchase |
| 9 | DEF | Aug 8 | Payment |
+---+--------+---------+----------+
Output result
+---+-------+----------------+--------------+
| | Acct | Last_trans_date|Last_transpay |
+---+-------+----------------+--------------+
| 1 | ABC | July 31 | Nov 5 |
| 2 | DEF | Mar 1 | Aug 8 |
| 3 | GFH | Mar 9 | Feb 7 |
+---+------+-----------------+--------------+
I read that using the WITH clauses could be an option, but struggling to understand it.
You can use conditional aggregation like so:
select acct,
max(case when trans_code = 'Purchase' then trans_date end) as last_purchase,
max(case when trans_code = 'Payment' then trans_date end) as last_payment
from mytable
group by acct
The syntax to insert the result of a query to another table varies across databases. In many of them, you can use:
create table newtable as
select ... -- above query
SQL Server is a notable exception, where you would need:
select ...
into newtable
from ...
group by ...
You can use conditional aggregation:
select acct, max(trans_date),
max(case when trans_code = 'Payment' then trans_date end)
from t
group by acct;
You can then insert this into an existing table or use the appropriate mechanism for your database to save the result as a new table.

How to expand table based on column value SQL Server [duplicate]

This question already has answers here:
Efficiently convert rows to columns in sql server
(5 answers)
Closed 2 years ago.
I have a table looks like this
+----+------+------+-------+
| ID | FY | Code | Value |
+----+------+------+-------+
| 1 | 2021 | A | 2 |
+----+------+------+-------+
| 1 | 2021 | B | 5 |
+----+------+------+-------+
| 1 | 2021 | C | 3 |
+----+------+------+-------+
| 2 | 2021 | A | 4 |
+----+------+------+-------+
| 2 | 2021 | B | 5 |
+----+------+------+-------+
| 2 | 2021 | C | 6 |
+----+------+------+-------+
I want to expand the code column to the following format:
+----+------+---+---+---+
| ID | FY | A | B | C |
+----+------+---+---+---+
| 1 | 2021 | 2 | 5 | 3 |
+----+------+---+---+---+
| 2 | 2021 | 4 | 5 | 6 |
+----+------+---+---+---+
I came up with an ugly way as to use multiple Where sub query and join them together, but there are a few values in 'Code' column which make things ugly.
Is there an elegant way of achieving this? (SQL Server)
Best,
Use conditional aggregation:
select
id,
fy,
max(case when code = 'A' then value end) as A,
max(case when code = 'B' then value end) as B,
max(case when code = 'C' then value end) as C
from mytable
group by id, fy

BigQuery Standard SQL Pivot Rows to Columns [duplicate]

This question already has answers here:
How to Pivot table in BigQuery
(7 answers)
Closed 2 years ago.
Im trying to query data that uses rows to store time series data using Standard SQL in BigQuery. Example data below. There will be way more Jobs than A-D
+-----+------------+--------------+-----------+
| Job | BatchDate | SuccessCount | FailCount |
+-----+------------+--------------+-----------+
| A | 2018-01-01 | 35 | 1 |
| A | 2018-01-07 | 13 | 6 |
| B | 2018-01-01 | 12 | 23 |
| B | 2018-01-07 | 67 | 12 |
| C | 2018-01-01 | 9 | 4 |
| C | 2018-01-07 | 78 | 6 |
| D | 2018-01-01 | 3 | 78 |
| D | 2018-01-07 | 99 | 5 |
+-----+------------+--------------+-----------+
I would like to have the following as output but cannot work out how to accomplish this in BigQuery.
SuccessCount values in column
+-----+------------+--------------+
| Job | 2018-01-01 | 2018-01-07 |
+-----+------------+--------------+
| A | 35 | 13 |
| B | 12 | 67 |
| C | 9 | 78 |
| D | 3 | 99 |
+-----+------------+--------------+
Is this sort of thing possible with BigQuery? Can anyone provide a working example?
Thanks
Edit
The data will grow over time, with new entries for each job per week. Is there a way to do this without having to hard code each BatchDate as a column?
If the Job is available on all rows, then conditional aggregation does what you want:
select job,
sum(case when batchdate = '2018-01-01' then SuccessCount else 0 end) as success_20180101,
sum(case when batchdate = '2018-01-07' then SuccessCount else 0 end) as success_20180107
from t
group by job
order by job;
use case when
select Job,
sum(case when batchdate='2018-01-01' then SuccessCount else 0 end) as s_01
sum(case when batchdate = '2018-01-07' then SuccessCount else 0 end) as s_07
from t group by job

How to select multiple count(*) values then group by a specific column

I've used SQL for a while but wouldn't say I'm at an advanced level. I've tinkered with trying to figure this out myself to no avail.
I have two tables - Transaction and TransactionType:
| **TransactionID** | **Name** | **TransactionTypeID** |
| 1 | Tom | 1 |
| 2 | Jim | 1 |
| 3 | Mo | 2 |
| 4 | Tom | 3 |
| 5 | Sarah | 4 |
| 6 | Tom | 1 |
| 7 | Sarah | 1 |
| **TransactionTypeID** | **TransactionType** |
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
The Transaction.TransactionTypeID is a Forein Key linked TransactionType.TransactionTypeID field.
Here's what I'd like to achieve:
I'd like a query (this will be a stored procedure) that returns three columns:
Name - the value of the Transaction.Name column.
NumberOfTypeATransactions - the count of the number of all transactions of type 'A' for that person.
NumberOfNonTypeATransactions - the count of the number of all transactions that are NOT of type A for that person, i.e. all other transaction types.
So, using the above data as an example, the result set would be:
| **Name** | **NumberOfTypeATransactions** | **NumberOfNonTypeATransactions** |
| Tom | 2 | 1 |
| Jim | 1 | 0 |
| Mo | 0 | 1 |
| Sarah | 1 | 1 |
I might also need to return the results based on a date period (which will be based on a 'transaction date' column in the Transaction table but I haven't finalized this requirement yet.
Any help in how I can achieve this would be much appreciated. Apologies of the layout of the tables is a bit odd - haven't worked out how to format them properly yet.
This is just conditional aggregation with a join:
select t.name,
sum(case when tt.TransactionType = 'A' then 1 else 0 end) as num_As,
sum(case when tt.TransactionType <> 'A' then 1 else 0 end) as num_notAs
from transaction t join
transactiontype tt
on tt.TransactionTypeID = t.TransactionTypeID
group by t.name;