I have a table with two columns id and value where id integer datatype and value is decimal datatype
Output should be like that:
1,13.0264757,77.6361745
2,13.0276974,77.6327644
I use pivot operator but it is not working properly. Below query is my workout
select 1, 2, 3
from (
select id, value
from sampletest
) as srctable
pivot
(
sum(value)
for id in ([1],[2],[3])
) as pivttabl
SQL tables represent unordered sets. You can get values onto the rows using conditional aggregation. For instance, for two rows:
select min(case when column_id = 1 then value end),
min(case when column_id = 2 then value end),
min(case when column_id = 3 then value end)
from t
union all
select max(case when column_id = 1 then value end),
max(case when column_id = 2 then value end),
max(case when column_id = 3 then value end) ;
Note: This is not the results that you specify in your question.
If you have an ordering column, you can express what you want as:
select min(case when column_id = 1 then value end),
min(case when column_id = 2 then value end),
min(case when column_id = 3 then value end)
from (select t.*,
row_number() over (partition by column_id order by <ordering column>) as seqnum
from t
) t
group by seqnum;
If you don't have an ordering column of some sort, then you cannot reliably do what you want. Instead, you should fix your data model so the data has the information you need. This is usually handled by having an identity column; such a column is ordered by the "insert-order" of the rows into the table.
Related
i have been trying to solve this one image
my initial idea is like this
select name,
CASE
when count(name) = 1 then get first distinct value
when count(name) = 2 then get first distinct value
else get first distinct value
END as val1,
CASE
when count(name) = 1 then null
when count(name) = 2 then get second distinct value
else get second distinct value
END as val2,
CASE
when count(name) = 1 then null
when count(name) = 2 then null
else get third distinct value
END as val3
into desired_table
from source_table
group by name
is my attempt feasible? if so, how do i access the first, second and third distinct values?
use pivot . Your output table was incorrect. The correct form is available in db<>fiddle.
select name,x as value1,y as value2,z as value3
from
(
select *
from t1
) as SourceTable
pivot
(
max(value) for value in(x,y,z)
) as PivotTable
demo in db<>fiddle
You can use conditional aggregation along with row_number():
select name,
max(case when seqnum = 1 then value end) as value_1,
max(case when seqnum = 2 then value end) as value_2,
max(case when seqnum = 3 then value end) as value_3
into desired_table
from (select s.*,
row_number() over (partition by name order by value) as seqnum
from source_table s
) s
group by name;
How to transform rows to column group by:
Desired result would be like this:
If you have a column that specifies the ordering, you can use conditional aggregation:
select max(case when columnname = 'SupplierGSTin' then value end) as SupplierGSTin,
max(case when columnname = 'DocumentNumber' then value end) as DocumentNumber,
max(case when columnname = 'SupplyType' then value end) as SupplyType
from (select t.*,
row_number() over (partition by columnname order by ?) as seqnum
from t
) t
group by rownum;
The ? is for the column that specifies the ordering.
I have a table Test with two columns.
Id Value
1 A
1 B
1 C
I want to get the result like below,
Id Value1 Value2 value3
1 A B C
How can I done this in SQL Server.
This is a pivot, but you don't have a column for the pivoting. row_number() can provide that. I usually use conditional aggregations for this.
select id,
max(case when seqnum = 1 then value end) as value1,
max(case when seqnum = 2 then value end) as value2,
max(case when seqnum = 3 then value end) as value3
from (select t.*,
row_number() over (partition by id order by (select null)) as seqnum
from t
) t
group by id;
Note that SQL tables represent unordered sets. So, there is no information about ordering and the values could be in any order. If a column does specify the ordering, then include that in the order by rather than select null.
Consider following 3 column table structure:
id, b_time, b_type
id is a string, there will be multiple rows with the same id in the table.
b_time is timestamp and b_type can have any one of 2 possible values - 'A' or 'B'.
I want to select all the rows that fulfill one of the 2 conditions, priority wise:
For all ids, select the row with highest timestamp, where b_type='A'.
If for an id, there are no rows where b_type='A', select the row with highest timestamp, irrespective of the b_type value.
Please suggest the sql query which should tackle this problem(even if it requires creation of temporary intermediate tables).
Figured out a simple and intuitive way to do this:
SELECT * FROM
(SELECT id
, b_time
, b_type
, ROW_NUMBER() OVER (PARTITION BY id ORDER BY b_type ASC,b_time DESC) AS RN
FROM your_table
)
WHERE RN = 1
with nottypea as (select id, max(b_time) as mxtime
from tablename
group by id
having sum(case when b_type = 'A' then 1 else 0 end) = 0)
, typea as (select id, max(b_time) as mxtime
from tablename
group by id
having sum(case when b_type = 'A' then 1 else 0 end) >= 1)
select id,mxtime,'B' as typ from nottypea
union all
select id,mxtime,'A' as typ from typea
Need to convert this:
DATE VALUE
18-DEC-15 2877544
17-DEC-15 2974276
16-DEC-15 4862020
into
18-DEC-15 17-DEC-15 16-DEC-15
2877544 2974276 4862020
The dates are updated everyday and I need to pick only the latest 3 dates and convert them into columns with the corresponding values below.
I tried using Pivots but I'm able to create the column headers dynamically.
Try this
WITH pivot_data AS (
select date, value from table)
SELECT *
FROM pivot_data
PIVOT (
max(value) --<-- pivot_clause
FOR table --<-- pivot_for_clause
);
A SQL query has well-defined column names, so for variable column names you need dynamic SQL. But, you can do what you want with fixed names:
select max(case when seqnum = 1 then value end) as MostRecentDay,
max(case when seqnum = 2 then value end) as SecondMostRecentDay,
max(case when seqnum = 3 then value end) as ThirdMostRecentDay
from (select t.*, dense_rank() over (order by date desc) as seqnum
from t
) t;
You could even add three columns specifying the date values:
select max(case when seqnum = 1 then value end) as MostRecentDay,
max(case when seqnum = 2 then value end) as SecondMostRecentDay,
max(case when seqnum = 3 then value end) as ThirdMostRecentDay,
max(case when seqnum = 1 then date end) as MostRecentDate,
max(case when seqnum = 2 then date end) as SecondMostRecentDate,
max(case when seqnum = 3 then date end) as ThirdMostRecentDate
from (select t.*, dense_rank() over (order by date desc) as seqnum
from t
) t;
Use Conditional Aggregate to pivot the data
select MAX(case when "DATE" = '18-DEC-15' then VALUE END) as '18-DEC-15',
MAX(case when "DATE" = '17-DEC-15' then VALUE END) as '17-DEC-15',
MAX(case when "DATE" = '16-DEC-15' then VALUE END) as '16-DEC-15'
from yourtable
Note : since dates are unknown, you need to use EXECUTE IMMEDIATE