I have the following table.
| col1 | col2 | col3 | col4 |
| ---- | ---- | ---- | ---- |
| 123 | 345 | LA | 001 |
| 123 | 345 | AB | |
| 123 | 345 | LA | |
| 123 | 345 | | |
| abc | cde | LA | |
| abc | cde | | |
| abc | cde | AB | |
| abc | cde | LA | |
| ooo | zzz | LA | |
| ooo | zzz | LA | 001 |
| ooo | zzz | LA | |
| ooo | zzz | LA | 001 |
| 12 | 35 | LA | |
| 12 | 35 | LA | |
| 12 | 35 | LA | |
| 12 | 35 | LA | |
I would like to select for each group of col1 & col2, col3 must be AB if it is present in the group, else blank, and col4 should be the non-blank if non-blank value is present, else it should be blank. col4 for each group will either have a unique non-blank value or blank.
Desired output:
| col1 | col2 | col3 | col4 |
|------|------|------|------|
| 123 | 345 | AB | 001 |
| abc | cde | AB | |
| ooo | zzz | | 001 |
| 12 | 35 | | |
Desired code:
select col1, col2,
(AB if AB present else blank) as col3,
(non-blank value if non-blank is present else blank) as col4
from test
group by col1, col2;
What I have tried so far:
select col1, col2,
max(col4) as col4
from test
group by col1, col2;
I don't know how to do it for col3
SQL Fiddle: https://www.db-fiddle.com/f/dtEiDdu6Arn6VQTGwMXm4q/0
NOTE:
I require a vendor agnostic solution. I think an RDBMS specific solution might work in the platform I use, but I would have to test out that answer/solution and get back to you though.
I am not querying from the source, but from a grid, so I am not using an RDBMS at the backend.
For the column col3 you need a CASE statement and for the column col4 simply MAX() (or MIN()):
select
col1,
col2,
case when sum(case when col3 = 'AB' then 1 else 0 end) > 0 then 'AB' else null end col3,
max(col4) col4
from test
group by col1, col2;
See the demo.
Results:
| col1 | col2 | col3 | col4 |
| ---- | ---- | ---- | ---- |
| 12 | 35 | | |
| 123 | 345 | AB | 001 |
| abc | cde | AB | |
| ooo | zzz | | 001 |
This is a prioritization query. row_number() is often used:
select col1, col2, (case when col3 = 'AB' then col3 end) as col3,
col4
from (select t.*,
row_number() over (partition by col1, col2
order by (case when col3 = 'AB' then 1 else 2 end),
(case when col4 <> '' then 1 else 2 end)
) as seqnum
from t
) t
where seqnum = 1;
Check This-
SELECT B.col1,B.col2,B.N_Col3,MAX(B.col4)
FROM
(
SELECT your_table.*,A.col3 N_Col3
FROM your_table
LEFT JOIN
(
SELECT * FROM your_table
WHERE col3 = 'AB'
)A
ON A.col1 = CTE.col1 AND A.col2 = CTE.col2
)B
GROUP BY B.col1,B.col2,B.N_Col3
ORDER BY 3 DESC
select col1, col2, max(col3) col3, max(col4) col4
from
(
select col1, col2, case when col3 = 'AB' THEN 'AB' ELSE ' ' END col3, max(COL4) col4
from #table
group by col1, col2, case when col3 = 'AB' THEN 'AB' ELSE ' ' END
) A
group by col1, col2
Related
I have to populate a teradata table from another source where that can be simplify like that:
+------+------+------------+------------+
| Col1 | Col2 | Col3 | Col4 |
+------+------+------------+------------+
| 1234 | 0 | 01/01/2009 | 01/04/2019 |
| 1234 | 3 | 01/01/2010 | 01/05/2020 |
| 2345 | 1 | 20/02/2013 | 01/04/2019 |
| 2345 | 0 | 20/02/2013 | 01/04/2018 |
| 2345 | 2 | 31/01/2009 | 01/04/2017 |
| 3456 | 0 | 01/01/2009 | 01/04/2019 |
| 3456 | 1 | 01/01/2015 | 01/04/2019 |
| 3456 | 1 | 01/01/2015 | 01/05/2017 |
| 3456 | 3 | 01/01/2015 | 01/04/2019 |
+------+------+------------+------------+
Col1 is duplicated in source so we have rules to select the right row (with col1 unique in final result)
For if value in col1 :
If value is duplicated then select the most recent date in Col3
If (and only if) it is still duplicated then select row with col2=1
If still duplicated then select most recent date in col4.
Considering the the previous table we should get the following result :
+------+------+------------+------------+
| Col1 | Col2 | Col3 | Col4 |
+------+------+------------+------------+
| 1234 | 3 | 01/01/2010 | 01/05/2020 |
| 2345 | 1 | 20/02/2013 | 01/04/2019 |
| 3456 | 1 | 01/01/2015 | 01/04/2019 |
+------+------+------------+------------+
I start using partition by to group each value occurrences in col 3 but i have no good idea on how to apply the conditions for each partion in a sql query
Thank you for your help
You can use QUALIFY in Teradata to simplify the syntax:
SELECT col1, col2, col3, col4
FROM mytable
QUALIFY ROW_NUMBER() OVER(
PARTITION BY col1 -- Group rows by "col1" values
ORDER BY col3 DESC, CASE WHEN col2 = 1 THEN 1 ELSE 2 END, col4 DESC -- Order rows
) = 1 -- Get "first" row in each group
Otherwise, this is the same as the answer above.
You can use row_number():
select t.*
from (select t.*,
row_number() over (partition by col1
order by col3 desc,
(case when col2 = 1 then 1 else 2 end),
col4 desc
) as seqnum
from t
) t
where seqnum = 1;
I have sql table as follows
+-----------------------------+
| |col1 | col2 | col3| col4| |
+-----------------------------+
| _______________________ |
| | a | 3 | d1 | 10 | |
| | a | 6 | d2 | 15 | |
| | b | 2 | d2 | 8 | |
| | b | 30 | d1 | 50 | |
+-----------------------------+
I would like transform the above table into below, where the transformation is
col4 = col4 - (col4 % min(col2) group by col1)
+------------------------------+
| |col1 | col2 | col3| col4| |
+------------------------------+
| ____________________________ |
| |a | 3 | d1 | 9 | |
| |a | 6 | d2 | 15 | |
| |b | 2 | d2 | 8 | |
| |b | 30 | d1 | 50 | |
| |
+------------------------------+
I could read the above table in application code to do transformation manually, was wondering if it was possible to offload the transformation to sql
Just run a simple select query for this:
select col1, col2, col3,
col4 - (col4 % min(col2) over (partition by col1))
from t;
There is no need to actually modify the table.
You can use a multi-table UPDATE to achieve your desired result, joining your table to a table of MIN(col2) values:
UPDATE table1
SET col4 = col4 - (col4 % t2.col2min)
FROM (SELECT col1, MIN(col2) AS col2min
FROM table1
GROUP BY col1) t2
WHERE table1.col1 = t2.col1
Output:
col1 col2 col3 col4
a 3 d1 9
a 6 d2 15
b 2 d2 8
b 30 d1 50
Demo on dbfiddle
I need something like this in MS ACCESS SQL
SELECT
ID,
col1,
col2,
random(col3)
FROM
table
GROUP BY
ID,
col1,
col2
NOTE:
I want to remove duplicates choosing random value of col3.
INPUT:
+----+------+------+------+
| Id | col1 | col2 | col3 |
+----+------+------+------+
| 1 | A | B | 7 |
+----+------+------+------+
| 1 | A | B | 10 |
+----+------+------+------+
RESULT:
+----+------+------+------+
| Id | col1 | col2 | col3 |
+----+------+------+------+
| 1 | A | B | 7 |
+----+------+------+------+
REQUERY:
+----+------+------+------+
| Id | col1 | col2 | col3 |
+----+------+------+------+
| 1 | A | B | 10 |
+----+------+------+------+
I have a table (TestTable) as follows
PK | COL1 | COL2 | COL3
1 | 3 | NULL | NULL
2 | 3 | 43 | 1.5
3 | 4 | NULL | NULL
4 | 4 | NULL | NULL
5 | 4 | 48 | 10.5
6 | NULL | NULL | NULL
7 | NULL | NULL | NULL
8 | NULL | NULL | NULL
9 | 5 | NULL | NULL
10 | 5 | NULL | NULL
11 | 5 | 55 | 95
I would like a result as follows
PK | COL1 | COL2 | COL3
1 | 3 | 43 | 1.5
2 | 4 | 48 | 10.5
3 | 5 | 55 | 95
You can do this, But it won't give you a serial number for the PK:
SELECT
PK,
MAX(Col1) AS Col1,
MAX(Col2) AS Col2,
MAX(Col3) AS Col3
FROM TestTable
WHERE Col1 IS NOT NULL
AND Col2 IS NOT NULL
AND COL3 IS NOT NULL
GROUP BY PK;
| PK | COL1 | COL2 | COL3 |
|----|------|------|------|
| 2 | 3 | 43 | 1.5 |
| 5 | 4 | 48 | 10.5 |
| 11 | 5 | 55 | 95 |
If you want to generate a rownumber for the column pk, you can do this:
WITH CTE
AS
(
SELECT
PK,
MAX(Col1) AS Col1,
MAX(Col2) AS Col2,
MAX(Col3) AS Col3
FROM TestTable
WHERE Col1 IS NOT NULL
AND Col2 IS NOT NULL
AND COL3 IS NOT NULL
GROUP BY PK
), Ranked
AS
(
SELECT *, ROW_NUMBER() OVER(ORDER BY PK) AS RN
FROM CTE;
)
SELECT RN AS PK, Col1, COL2, COL3 FROM Ranked
SQL Fiddle Demo
This will give you:
| PK | COL1 | COL2 | COL3 |
|----|------|------|------|
| 1 | 3 | 43 | 1.5 |
| 2 | 4 | 48 | 10.5 |
| 3 | 5 | 55 | 95 |
This can be obtained in two steps like so:
1st step: Get rid of unnecessary rows:
delete from testTable
where Col1 is null
or Col2 is null
or Col3 is null
2nd step: Set the correck PK values using a CTE (update test table):
;with sanitizeCTE
as(
select ROW_NUMBER() over (order by PK) as PK,
Col1, Col2, Col3
from testTable
)
update t
set t.PK = CTE.PK
from testTable t
join sanitizeCTE cte
on t.Col1 = cte.Col1
and t.Col2 = cte.Col2
and t.Col3 = cte.Col3
Tested here: http://sqlfiddle.com/#!3/91e86/1
I have the table like this :
| Col1 | Col2 | col3 |
|:-----------|------------:|:------------:|
| type1 | 1 | aaaa |
| type3 | 101 | bbbb |
| type2 | 21 | cccc |
| type1 | 2 | aaa |
| type2 | 22 | bbb |
| type3 | 102 | ccc |
| type1 | 3 | aaax |
| type2 | 23 | bbbx |
| type3 | 103 | cccx |
I need output in following way...
| Col1 | Col2 | col3 |
|:-----------|------------:|:------------:|
| type1 | 1 | aaaa |
| type1 | 2 | aaa |
| type1 | 3 | aaax |
|
| type2 | 21 | cccc |
| type2 | 22 | bbb |
| type2 | 23 | bbbx |
|
| type3 | 101 | bbbb |
| type3 | 102 | ccc |
| type3 | 103 | cccx |
Please find some way to get such kind of output
And i have lot of records in this table but i need to get top 5 of each TYPE in same order.....
Try:
SELECT Col1,
Col2,
Col3
FROM(
SELECT
Col1,
Col2,
Col3,
ROW_NUMBER() OVER (PARTITION BY Col1 ORDER BY Col1, Col2, Col3) RNum
FROM YourTable
)X WHERE RNum<=5
Use the ORDER BY function
SELECT COL1, COL2, COL3
FROM MyTable ORDER BY COl1, COl2, COl3
You don't need to group this data because GROUP BY needs to aggregate some columns. but instead, use only ORDER BY clause.
SELECT *
FROM tableName
ORDER BY Col1 ASC, Col2 ASC, Col3 ASC