Grouping multiple lines onto one in Oracle SQL - sql

How can I get this data set in Image 1 to look like the data in Image 2. Basically rather than having each purchase on its own line I want to group by Name and have all that persons purchases on one line. They can buy a max of 5 items and my database is about 30 million lines worth of purchases.
P.S The date order is not important

You can use row_number() and conditional aggregation:
select name,
max(case when seqnum = 1 then item end) as item_1,
max(case when seqnum = 1 then date end) as date_1,
max(case when seqnum = 2 then item end) as item_2,
max(case when seqnum = 2 then date end) as date_2,
max(case when seqnum = 3 then item end) as item_3,
max(case when seqnum = 3 then date end) as date_3
from (select t.*,
row_number() over (partition by name order by date asc) as seqnum
from t
) t
group by name;

You can use PIVOT with row_number as follows:
Select * from
(select t.*,
row_number() over (partition by name order by date_purchased) rn
from your_table t
) PIVOT
(Max(item_purchased), max(date_purchased) For rn in (1,2,3));

Related

Combine multiple rows to single row group by Specific column

I have a table that looks similar to this here:
I would like to able to combine all that data when they have the same Id.
Which would look like this:
Use conditional aggregation:
select id,
max(case when seqnum = 1 then section end) as section1,
max(case when seqnum = 1 then value1 end) as section1_value1,
max(case when seqnum = 1 then value2 end) as section1_value2,
max(case when seqnum = 2 then section end) as section2,
max(case when seqnum = 2 then value1 end) as section2_value1,
max(case when seqnum = 2 then value2 end) as section2_value2
from (select t.*,
row_number() over (partition by id order by section) as seqnum
from t
) t
group by id;

How to retrieving data as customized format

I retrieved some data as below (image 01).
i used this query:
SELECT TOP (3) no, co, cdate, year
FROM main_backup
WHERE (no = 41505)
ORDER BY cdate DESC
But I want that, like this type as below (image 02)
You can use conditional aggregation and window functions:
select no,
max(case when seqnum = 1 then total end) as total_1,
max(case when seqnum = 1 then cdate end) as date_1,
max(case when seqnum = 2 then total end) as total_2,
max(case when seqnum = 2 then cdate end) as date_2,
max(case when seqnum = 3 then total end) as total_3,
max(case when seqnum = 3 then cdate end) as date_3
from (select t.*,
row_number() over (partition by no order by cdate desc) as seqnum
from t
) t
group by no

Pivoting multiple transactions per customer

I have a query which gives customer transactional info. Each customer has multiple transactions and designations these transactions go to.The query outputs CustomerId,Amount,Date,Designation. This has multiple rows for each customer.I want to pivot this so that there is only one row per customer.
I know this is not an ideal way to represent this data, but for the purpose of this particular use case, it has to be in this format. The number of columns will be (max of the number of transactions per customer) X 3
To pivot over a fixed list of transactions per client, you could use row_number() and conditional aggregation:
select
CustomerId,
max(case when rn = 1 then Amount end) Amount1,
max(case when rn = 1 then DateReceived end) DateReceived1,
max(case when rn = 1 then Account end) Account1,
max(case when rn = 2 then Amount end) Amount2,
max(case when rn = 2 then DateReceived end) DateReceived2,
max(case when rn = 2 then Account end) Account2,
max(case when rn = 3 then Amount end) Amount3,
max(case when rn = 3 then DateReceived end) DateReceived3,
max(case when rn = 3 then Account end) Account3
from (
select t.*, row_number() over(partition by CustomerId order by DateReceived) rn
from mytable t
) t
group by CustomerId
This handles up to 3 transactions per client. For more, you can expand the select clause with more tuples of max(case when rn = ... then ... end) expressions.

Converting three Rows to one row

I'm trying to convert Rows to Columns from a MS SQL table...
my MS SQL table is like...
I want to SELECT the output as below...
I tried with pivot tables and cross join.. unfortunately could not make it.
any help is highly appreciated
You can use ROW_NUMBER() in a subquery to rank records, and the do conditional aggregation in the outer query:
SELECT
id,
SubId,
MAX(CASE WHEN rn = 1 THEN code END) Code1,
MAX(CASE WHEN rn = 1 THEN TotalAmount END) Code1TotalAmount,
MAX(CASE WHEN rn = 1 THEN TotalDays END) Code1TotalDays,
MAX(CASE WHEN rn = 2 THEN code END) Code2,
MAX(CASE WHEN rn = 2 THEN TotalAmount END) Code2TotalAmount,
MAX(CASE WHEN rn = 2 THEN TotalDays END) Code2TotalDays,
MAX(CASE WHEN rn = 3 THEN code END) Code3,
MAX(CASE WHEN rn = 3 THEN TotalAmount END) Code3TotalAmount,
MAX(CASE WHEN rn = 3 THEN TotalDays END) Code3TotalDays
FROM (
SELECT
t.*,
ROW_NUMBER() OVER(PARTITION BY ID, SubId ORDER BY code) rn
FROM mytable t
) x
GROUP BY ID, SubId

need to convert data in multiple rows with same ID into 1 row with multiple columns

I reviewed versions of my question already addressed, but some of the good tips I found (using rank() over (partition...) for example, do not seem to work in the Sybase version I am on.
I am hoping to run a procedure that pulls data organized as follows:
Email | Preference
email1 | PreferenceXYZ
email1 | PreferenceABC
And render it in a table like the following:
Email | Preference1 | Preference2
email1 | PreferenceXYZ | PreferenceABC
In essence, I have multiple records for the same person (best identified via email record as a unique identifier) and I want to capture these multiple preferences for a given user and create 1 individual record per user (per email).
If you only have two preferences, then you can use min() and max():
select email, min(preference) as preference1,
(case when min(preference) <> max(preference) then max(preference) end) as preference2
from t
group by email;
EDIT:
If you have up to seven values, then pivot using row_number():
select email,
max(case when seqnum = 1 then preference end) as preference1,
max(case when seqnum = 2 then preference end) as preference2,
max(case when seqnum = 3 then preference end) as preference3,
max(case when seqnum = 4 then preference end) as preference4,
max(case when seqnum = 5 then preference end) as preference5,
max(case when seqnum = 6 then preference end) as preference6,
max(case when seqnum = 7 then preference end) as preference7
from (select t.*, row_number() over (partition by email order by preference) as seqnum
from t
) t
group by email;
EDIT II:
You can actually do this with a correlated subquery instead of row_number():
select email,
max(case when seqnum = 1 then preference end) as preference1,
max(case when seqnum = 2 then preference end) as preference2,
max(case when seqnum = 3 then preference end) as preference3,
max(case when seqnum = 4 then preference end) as preference4,
max(case when seqnum = 5 then preference end) as preference5,
max(case when seqnum = 6 then preference end) as preference6,
max(case when seqnum = 7 then preference end) as preference7
from (select t.*,
(select count(*)
from t t2
where t2.email = t.email and
t2.preference <= t.preference
) as seqnum
from t
) t
group by email;