sql17 - The column 'id' was specified multiple times for 't' - sql

I write below query in mssm 17.
select t.id,
max (case when seq=1 then label end) as label-1,
max (case when seq=2 then label end) as label-2,
max (case when seq=3 then label end) as label-3,
max (case when seq=4 then label end) as label-4,
max (case when seq=5 then label end) as label-5,
from (select t1.*,t2.*,
row-number () over (partition by t1.id order by t2.label) as seq
from table1 t1 inner join table2 t2 on t1.id=t2.sequence
) t
group by t.id
The query don't execute and the error is: The column 'id' was specified multiple times for 't'.
I want to merge all rows with similar id into one row and different columns.
can anybody help me and solve the error?

You have multiple issues with the query. This specific issue is that id is in both table1 and table2. So, just select the columns that you need in the outer query.
Also, - is not allowed for column aliases. And the correct function name is row_number(), not row-number():
select t.id,
max(case when seq=1 then label end) as label_1,
max(case when seq=2 then label end) as label_2,
max(case when seq=3 then label end) as label_3,
max(case when seq=4 then label end) as label_4,
max(case when seq=5 then label end) as label_5,
from (select t1.id, t2.label,
row_number() over (partition by t1.id order by t2.label) as seq
from table1 t1 inner join
table2 t2
on t1.id = t2.sequence
) t
group by t.id

Related

SQL Function for updating column with values

Those who have helped me before, i tend to use SAS9.4 a lot for my day to day work, however there are times when i need to use SQL Server
There is a output table i have with 2 variables (attached output.csv)
output table
ID, GROUP, DATE
The table has 830 rows:
330 have a "C" group
150 have a "A" group
50 have a "B" group
the remaining 300 have group as "TEMP"
within SQL i do not now how to programatically work out the total volume of A+B+C. The aim is to update "TEMP" column to ensure there is an Equal amount of "A" and "B" totalling 250 of each (the remainder of the total count)
so the table totals
330 have a "C" group
250 have a "A" group
250 have a "B" group
You want to proportion the "temp" to get equal amounts of "A" and "B".
So, the idea is to count up everything in A, B, and Temp and divide by 2. That is the final group size. Then you can use arithmetic to allocate the rows in Temp to the two groups:
select t.*,
(case when seqnum + a_cnt <= final_group_size then 'A' else 'B' end) as allocated_group
from (select t.*, row_number() over (order by newid()) as seqnum
from t
where group = 'Temp'
) t cross join
(select (cnt_a + cnt_b + cnt_temp) / 2 as final_group_size,
g.*
from (select sum(case when group = 'A' then 1 else 0 end) as cnt_a,
sum(case when group = 'B' then 1 else 0 end) as cnt_b,
sum(case when group = 'Temp' then 1 else 0 end) as cnt_temp
from t
) g
) g
SQL Server makes it easy to put this into an update:
with toupdate as (
select t.*,
(case when seqnum + a_cnt <= final_group_size then 'A' else 'B' end) as allocated_group
from (select t.*, row_number() over (order by newid()) as seqnum
from t
where group = 'Temp'
) t cross join
(select (cnt_a + cnt_b + cnt_temp) / 2 as final_group_size,
g.*
from (select sum(case when group = 'A' then 1 else 0 end) as cnt_a,
sum(case when group = 'B' then 1 else 0 end) as cnt_b,
sum(case when group = 'Temp' then 1 else 0 end) as cnt_temp
from t
) g
) g
)
update toupdate
set group = allocated_group;
I'd go with a top 250 update style approach
update top (250) [TableName] set Group = 'A' where exists (Select * from [TableName] t2 where t2.id = [TableName].id order by newid()) and Group = 'Temp'
update top (250) [TableName] set Group = 'B' where exists (Select * from [TableName] t2 where t2.id = [TableName].id order by newid()) and Group = 'Temp'

sql transformation - rows to column

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;

SQL count and combine

I'm setting up a query to change the data of a form, count data and format it. At this moment I've got a table with vertical data. The data is shown in the image below.
What I want to do is to create Group by on Number, after that count how many times a specific TypePak there is and split it to the right. As shown in the image on the right.
I've tried to do Pivot and it helped for a part of it, but that's not a good method. Then i've tried XML Path.
PIVOT
FROM dbo.des_ombouw
GROUP BY Number, typePak) src
pivot
(
max(Expr1)
for typePak in ([COLLI],[DOOS],[pallet],[Envelop])
) piv1
XML Path
select distinct Number, abc = STUFF((
select ',' + TypePak
from des_ombouw t1
where t1.Number = t2.Number
FOR XML PATH ('')),1,1,'')
from des_ombouw t2
In the image is what I want. There are more columns that has to be added, like weight of some package.
One of the problems too is that there are coming more columns, so this is not all!
Two steps of aggregation with row_number() may do what you want:
select d.number,
max(case when seqnum = 1 then cnt end) as cnt_1,
max(case when seqnum = 1 then typepak end) as typepak_1,
max(case when seqnum = 2 then cnt end) as cnt_2,
max(case when seqnum = 2 then typepak end) as typepak_2,
max(case when seqnum = 3 then cnt end) as cnt_3,
max(case when seqnum = 3 then typepak end) as typepak_3,
max(case when seqnum = 4 then cnt end) as cnt_4,
max(case when seqnum = 4 then typepak end) as typepak_4
from (select d.number, d.typepak, count(*) as cnt,
row_number() over (partition by d.number order by count(*) desc) as seqnum
from dbo.des_ombouw d
) d
group by d.number

SQL query to return history as flat format

Looking for help with an SQL query to turn a history table into flat file format with up to 5 instances of results on table B. I have only shown 2 instances in the results. For a bonus point can these be sorted by EFF_DATE ascending?!
My query so far is
SELECT a.REFNO, a.M_NAME, b.EFF_DATE, b.VAL
FROM TABLEA a INNER JOIN TABLEB b ON (a.REFNO=b.REFNO)
WHERE a.REFNO = '1'
This is fine for returning results once per row, but how do I modify so up to 5 EFF_DATE and VAL instances are repeated on one row. The dates can be any date and ideally would like them sorted ascending left to right. Only those rows on TABLEB where Val > 0 should be included.
If you know the number of columns you want in the history, then you can use conditional aggregation or pivot. The challenge is not having a column for the pivot.
You can easily generate one, though, using ROW_NUMBER():
SELECT a.REFNO, a.M_NAME,
MAX(CASE WHEN seqnum = 1 THEN b.EFF_DATE END) as EFF_DATE_1,
MAX(CASE WHEN seqnum = 1 THEN b.VAL END) as VAL_1,
MAX(CASE WHEN seqnum = 2 THEN b.EFF_DATE END) as EFF_DATE_2,
MAX(CASE WHEN seqnum = 2 THEN b.VAL END) as VAL_2,
MAX(CASE WHEN seqnum = 3 THEN b.EFF_DATE END) as EFF_DATE_3,
MAX(CASE WHEN seqnum = 3 THEN b.VAL END) as VAL_3
FROM TABLEA a INNER JOIN
(SELECT b.*,
ROW_NUMBER() OVER (PARTITION BY REFNO ORDER BY EFF_DATE) as seqnum
FROM TABLEB b
) b
ON a.REFNO = b.REFNO
WHERE a.REFNO = '1'
GROUP BY a.REFNO, a.M_NAME;
If you don't know the number of columns in the output, then you will need dynamic SQL or to do the formatting at the application layer.

SQL query to select rows using max aggregate and putting them together

I have a table in which the first column is the key value. I have to select one row for each of the key values (select the one with maximum "count" field ) and then arrange them adjacent to each other. I wrote this query for this purpose:
SELECT name as "name",
MAX(CASE WHEN key_id=8 THEN count ELSE 0.0 END) AS "key_1",
key_value as "key_1_value",
MAX(CASE WHEN key_id=9 THEN count ELSE 0.0 END) AS "key_2",
key_value as "key_2_value",
MAX(CASE WHEN key_id=10 THEN count ELSE 0.0 END) AS "key_3",
key_value as "key_2_value"
FROM table1 GROUP BY name;
The result I get is :
name1 281000018371 0.881841 247000421624 0.881841 285000032094 0.881841
The values for the count is correct i.e. the maximum value of count for that particular key_id but the key_value is correct only for the first key_id which is repeated for the other two.
Can someone please tell me how to change this query so that I get the key_value from the row with corresponding key_id and max(count).
Is this what you're trying to do?
SELECT
name as "name",
MAX(CASE WHEN key_id=8 THEN count ELSE 0.0 END) AS "key_1",
MAX(CASE WHEN key_id=8 THEN key_value END) AS "key_1_value",
MAX(CASE WHEN key_id=9 THEN count ELSE 0.0 END) AS "key_2",
MAX(CASE WHEN key_id=9 THEN key_value END) AS "key_2_value",
MAX(CASE WHEN key_id=10 THEN count ELSE 0.0 END) AS "key_3",
MAX(CASE WHEN key_id=10 THEN key_value END) AS "key_3_value"
FROM table1
GROUP BY name;
Without sample data, I'm assuming that you're looking at multiple rows and trying to get certain keys onto columns. Your original query is pulling the same value for every column.
EDIT:
Performance would be horrible on this if you have any major amounts of data, but you could try doing this ...
SELECT
name as "name",
MAX(CASE WHEN key_id=8 THEN count ELSE 0.0 END) AS "key_1",
(SELECT TOP 1 key_value FROM Table1 k1 WHERE k1.name = Table1.name AND key_id = 8 ORDER BY Count DESC) as "key_1_value",
MAX(CASE WHEN key_id=9 THEN count ELSE 0.0 END) AS "key_2",
(SELECT TOP 1 key_value FROM Table1 k2 WHERE k2.name = Table1.name AND key_id = 9 ORDER BY Count DESC) as "key_2_value",
MAX(CASE WHEN key_id=10 THEN count ELSE 0.0 END) AS "key_3",
(SELECT TOP 1 key_value FROM Table1 k3 WHERE k3.name = Table1.name AND key_id = 10 ORDER BY Count DESC) as "key_3_value"
FROM table1
GROUP BY name;
Hmm...maybe:
SELECT distinct name, b.MaxCount, b.Key_Value, c.MaxCount, c.Key_Value, d.MaxCount, d.Key_Value
from table1 a
left join
(SELECT key_Value, MAX(ifnull((count,0)) as MaxCount from table1 where key_id =8 group by key_Value) b
on a.name = b.name
left join
(SELECT key_Value, MAX(ifnull((count,0)) as MaxCount from table1 where key_id =9 group by key_Value) c
on a.name = b.name
left join
(SELECT key_Value, MAX(ifnull((count,0)) as MaxCount from table1 where key_id =10 group by key_Value) d
on a.name = b.name
group by name
I assume your join condition.
You got an IO error. This could be because of the isnull should be ifnull in SQLITE. sorry for that.