I have two table as below.
Table 1
+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 |
+------+------+------+------+
| 1 | 1.5 | 1.5 | 2.5 |
| 1 | 2.5 | 3.5 | 1.5 |
+------+------+------+------+
Table 2
+------+--------+
| Col1 | Col2 |
+------+--------+
| 1 | 12345 |
| 1 | 678910 |
+------+--------+
I want the result as below.
+------+------+------+------+-------+--------+
| Col1 | Col2 | Col3 | Col4 | Col5 | Col6 |
+------+------+------+------+-------+--------+
| 1 | 4 | 5 | 4 | 12345 | 678910 |
+------+------+------+------+-------+--------+
Here Col2, Col3 and Col4 is the aggregate of value from Col2,3,4 in Table 1. And rows from Table 2 are transposed to Columns in the result.
I use Oracle 11G and tried the PIVOT option. But I couldn't aggregate values from Column 2,3,4 in Table 1.
Is there any function available in Oracle which provides direct solution without any dirty work around?
Thanks in advance.
Since you will always have only 2 records in second table simple grouping and join will do.
Since I dont have tables I am using CTEs and Inline views
with cte1 as (
select 1 as col1 , 1.5 as col2 , 1.5 as col3, 2.5 as col4 from dual
union all
select 1 , 2.5 , 3.5 , 1.5 fom dual
) ,
cte2 as (
select 1 as col1 , 12345 as col2 fom dual
union all
select 1,678910 fom dual )
select* from(
(select col1,sum(col2) as col2 , sum(col3) as col3,sum(col4) as col4
from cte1 group by col1) as x
inner join
(select col1 ,min(col2) as col5 ,max(col2) as col from cte2
group by col1
) as y
on x.col1=y.col1)
with
mytab1 as (select col1, col2, col3, col4, 0 col5, 0 col6 from tab1),
mytab2 as
(
select
col1, 0 col2, 0 col3, 0 col4, "1_COL2" col5, "2_COL2" col6
from
(
select
row_number() over (partition by col1 order by rowid) rn, col1, col2
from
tab2
)
pivot
(
max(col2) col2
for rn in (1, 2)
)
)
select
col1,
sum(col2) col2,
sum(col3) col3,
sum(col4) col4,
sum(col5) col5,
sum(col6) col6
from
(
select * from mytab1 union all select * from mytab2
)
group by
col1
Hello You can use the below query
with t1 (col1,col2,col3,col4)
as
(
select 1,1.5,1.5,2.5 from dual
union
select 1,2.5,3.5,1.5 from dual
),
t2 (col1,col2)
as
(
select 1,12345 from dual
union
select 1,678910 from dual
)
select * from
(
select col1
,max(decode(col2,12345,12345)) as co5
,max(decode(col2,678910,678910)) as col6
from t2
group by col1
) a
inner join
(
select col1,sum(col2) as col2,sum(col3) as col3,sum(col4) as col4
from t1
group by col1
) b
on a.col1=b.col1
Pivot only the second table. You can then do GROUP BY on the nested UNION ALL between table1 (col5 and col6 are null for subsequent group by) and pivoted table2 (col2, col3, col4 are null for subsequent group by).
Related
If we have two or more tables without the same column.
Table 1
Col1 | Col2
1 | 2
3 | 4
Table 2
Col3 | Col4
5 | 6
7 | 8
We would like to combine these two tables and save it into a new one
New Table
Col1 | Col2 | Col3 | Col4
1 | 2 | 5 | 6
3 | 4 | 7 | 8
I don't have any idea what must I use. If using join it's must have same table to paring but this don't have same column
NB: I'm using SQL SERVER
You could use the row_number window function to create a fake column to join on:
SELECT co1l, col2, col3, col4
FROM (SELECT col1, col2, ROW_NUMBER() OVER (ORDER BY col1, col2) AS rn
FROM table1) t1
JOIN (SELECT col3, col4, ROW_NUMBER() OVER (ORDER BY col3, col4) AS rn
FROM table2) t2 ON t1.rn = t2.rn
I have some incoming rows in the below format.
| Col1 | Col2 | Col3 |
| 1 | A | 1 |
| 1 | A | 1,2 |
| 1 | A | 1,3 |
| 1 | A | 2,4 |
Desired outputsql is
| Col1 | Col2 | Col3 |
| 1 | A | 1,2,3,4 |
Basically, group all rows based on Col1 and Col2 and then concatenate and remove duplicates from Col3.
SELECT COL1, COL2, {?????}
FROM TABLEA
GROUP BY COL1, COL2;
I could not think much at this moment. Any pointers would be much appreciated. I am inclined to WX2 database, but any ANSI compliant snippet would be helpful.
For Postgres use this:
select col1, col2, string_agg(distinct col3, ',') as col3
from (
select col1, col2, x.col3
from tablea, unnest(string_to_array(col3, ',')) as x(col3)
) t
group by col1, col2;
This is largely ANSI compliant except for the string_to_array() and string_agg() function.
You could try with transpose or concatenation functions. The difficulty comes from the fact that col3 is varchar and a conversion is needed to get the distinct values.
With MySQL :
SELECT col1, col2, GROUP_CONCAT(DISTINCT col3) AS col3 FROM
(SELECT col1, col2, CONVERT(SUBSTR(col3, 1), UNSIGNED INTEGER) AS col3 FROM (
SELECT 1 AS col1, 'A' AS col2, '1' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '1,2' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '1,3' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '2,4' AS col3
) AS t
UNION ALL
SELECT col1, col2, CONVERT(SUBSTR(col3, 3), UNSIGNED INTEGER) AS col3 FROM (
SELECT 1 AS col1, 'A' AS col2, '1' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '1,2' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '1,3' AS col3 UNION ALL
SELECT 1 AS col1, 'A' AS col2, '2,4' AS col3
) AS t1
) AS t2
WHERE col3 <> 0
Result :
col1 | col2 | col3
1 | A | 1,2,3,4
For SQL Server: first concatenate all col3 values using STUFF method and INSERT INTO CTE table.Based on this CTE tables split all rows as individual into single column based on CTE table.Finally concate all DISTINCT strings with help of STUFF.
CREATE TABLE #table ( Col1 INT , Col2 VARCHAR(10) , Col3 VARCHAR(10))
INSERT INTO #table ( Col1 , Col2 , Col3 )
SELECT 1 , 'A' , '1' UNION ALL
SELECT 1 , 'A' , '1,2' UNION ALL
SELECT 1 , 'A' , '1,3' UNION ALL
SELECT 1 , 'A' , '2,4'
;WITH CTEValues ( Colval ) AS
(
SELECT STUFF ( ( SELECT ',' + Col3 FROM #table T2 WHERE T2.Col2 =
T1.col2 FOR XML PATH('') ),1,1,'')
FROM #table T1
GROUP BY Col2
)
SELECT * INTO #CTEValues
FROM CTEValues
;WITH CTEDistinct ( SplitValues , SplitRemain ) AS
(
SELECT SUBSTRING(Colval,0,CHARINDEX(',',Colval)),
SUBSTRING(Colval,CHARINDEX(',',Colval)+1,LEN(Colval))
FROM #CTEValues
UNION ALL
SELECT CASE WHEN CHARINDEX(',',SplitRemain) = 0 THEN SplitRemain ELSE
SUBSTRING(SplitRemain,0,CHARINDEX(',',SplitRemain)) END,
CASE WHEN CHARINDEX(',',SplitRemain) = 0 THEN '' ELSE
SUBSTRING(SplitRemain,CHARINDEX(',',SplitRemain)+1,LEN(SplitRemain))
END
FROM CTEDistinct
WHERE SplitRemain <> ''
)
SELECT STUFF ( ( SELECT DISTINCT ',' + SplitValues FROM CTEDistinct T2
FOR XML PATH('') ),1,1,'')
I have a table with following columns and 2 rows :
COL1,COL2,COL3,NAME,DATE
Value of COL1,COL2,COL3 in both rows are A,B,C. Value of NAME in 1st row is 'DEL' and 2nd row is 'LAP'. Value of DATE in 1st row is '11.12.13' and 2nd row is '13.11.13'.
Now i want a view with singlerow and following columns
COL1,COL2,COL3,DEL,LAP with values A,B,C,11.12.13,13.11.13.
Is that possible with pivot or any other function
thanks
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE table_name (COL1,COL2,COL3,N_NAME,D_DATE) AS
SELECT 'A','B','C', 'DEL', '11.12.13' FROM DUAL
UNION ALL SELECT 'A','B','C', 'LAP', '13.11.13' FROM DUAL
UNION ALL SELECT 'A','B','C', 'DEL', '12.12.13' FROM DUAL
UNION ALL SELECT 'A','B','C', 'LAP', '14.11.13' FROM DUAL;
Query 1:
If the combination of COL1, COL2, COL3 and N_Name is unique then you can do:
SELECT Col1,
Col2,
Col3,
MIN( CASE N_Name WHEN 'DEL' THEN D_Date END ) AS DEL,
MIN( CASE N_Name WHEN 'LAP' THEN D_Date END ) AS LAP
FROM table_name
GROUP BY
Col1,
Col2,
Col3
Results:
| COL1 | COL2 | COL3 | DEL | LAP |
|------|------|------|----------|----------|
| A | B | C | 11.12.13 | 13.11.13 |
Query 2:
However, if you can have multiple rows with the same combination of COL1, COL2, COL3 and N_Name and you want all of them returning (in date order) then you can do:
WITH indexed_data AS (
SELECT Col1,
Col2,
Col3,
N_Name,
D_Date,
ROW_NUMBER() OVER ( PARTITION BY Col1, Col2, Col3, N_Name ORDER BY D_Date ) AS idx
FROM table_name
)
SELECT Col1,
Col2,
Col3,
MIN( CASE N_Name WHEN 'DEL' THEN D_Date END ) AS DEL,
MIN( CASE N_Name WHEN 'LAP' THEN D_Date END ) AS LAP
FROM indexed_data
GROUP BY
Col1,
Col2,
Col3,
idx
ORDER BY
Col1,
Col2,
Col3,
idx
Results:
| COL1 | COL2 | COL3 | DEL | LAP |
|------|------|------|----------|----------|
| A | B | C | 11.12.13 | 13.11.13 |
| A | B | C | 12.12.13 | 14.11.13 |
with tab (COL1,COL2,COL3,N_NAME,D_DATE) as (
select 'A','B','C', 'DEL', '11.12.13' from dual union all
select 'A','B','C', 'LAP', '13.11.13' from dual)
select COL1, COL2, COL3,
min(decode(N_NAME, 'DEL', D_DATE, NULL)) DEL,
min(DECODE(N_NAME, 'LAP', D_DATE, NULL)) LAP
from tab
group by COL1, COL2, COL3
output
| COL1 | COL2 | COL3 | DEL | LAP |
|------|------|------|----------|----------|
| A | B | C | 11.12.13 | 13.11.13 |
Assuming that the common fields in both rows are COL1, COL2 and COL3.
SELECT a.col1,
a.col2,
a.col3,
a.date AS DEL,
b.date AS LAP
FROM yourtable AS a
INNER JOIN yourtable AS b
ON a.col1 = b.col1
AND a.col2 = b.col2
AND a.col3 = b.col3
AND a.name = 'DEL'
AND b.name = 'LAP'
Here is my sample table
Col1 Col2
A 1
B 1
A 1
B 2
C 3
I want to be able to select distinct records where all rows have the same value in Col1 and Col2. So my answer should be
Col1 Col2
A 1
C 3
I tried
SELECT Col1, Col2 FROM Table GROUP BY Col1, Col2
This gives me
Col1 Col2
A 1
B 1
B 2
C 3
which is not the result I am looking for. Any tips would be appreciated.
Try this out:
SELECT col1, MAX(col2) aCol2 FROM t
GROUP BY col1
HAVING COUNT(DISTINCT col2) = 1
Output:
| COL1 | ACOL2 |
|------|-------|
| A | 1 |
| C | 3 |
Fiddle here.
Basically, this makes sure that amount the different values for col2 are unique for a given col1.
Try this:
SELECT * FROM MYTABLE
GROUP BY Col1, Col2
HAVING COUNT(*)>1
For example SQLFiddle here
you can try either of the below -
select col1, col2 from
(
select 'A' Col1 , 1 Col2
from dual
union all
select 'B' , 1
from dual
union all
select 'A' ,1
from dual
union all
select 'B' ,2
from dual
)
group by col1, col2
having count(*) >1;
OR
select col1, col2
from
(
select col1, col2, row_number() over (partition by col1, col2 order by col1, col2) cnt
from
(
select 'A' Col1 , 1 Col2
from dual
union all
select 'B' , 1
from dual
union all
select 'A' ,1
from dual
union all
select 'B' ,2
from dual
)
)
where cnt>1;
If I have table:
+------------------------------------------------------------+
| Col 1 Col 2 Col 3 |
+------------------------------------------------------------+
| a72195fa-57ca-4849-b423-5595219c8f6b Val1 1 |
| a72195fa-57ca-4849-b423-5595219c8f6b Val2 1 |
| a72195fa-57ca-4849-b423-5595219c8f6b Val3 2 |
| a72195fa-57ca-4849-b423-5595219c8f6b Val4 3 |
| 2F6D0B9E-2221-4D18-A64E-ACCFB83EACC7 Val5 2 |
| 2F6D0B9E-2221-4D18-A64E-ACCFB83EACC7 Val6 2 |
| 2F6D0B9E-2221-4D18-A64E-ACCFB83EACC7 Val7 3 |
+------------------------------------------------------------+
For a given Col 1 Value, how do I return all records for smallest value in Col3. Meaning where [Col 1] = a72195fa-57ca-4849-b423-5595219c8f6b, I want to return:
+------------------------------------------------------------+
| Col 1 Col 2 Col 3 |
+------------------------------------------------------------+
| a72195fa-57ca-4849-b423-5595219c8f6b Val1 1 |
| a72195fa-57ca-4849-b423-5595219c8f6b Val2 1 |
+------------------------------------------------------------+
And where [Col 1] = 2F6D0B9E-2221-4D18-A64E-ACCFB83EACC7, I want to return:
+---------------------------------------------------------+
| Col 1 Col 2 Col 3 |
+---------------------------------------------------------+
| 2F6D0B9E-2221-4D18-A64E-ACCFB83EACC7 Val5 2 |
| 2F6D0B9E-2221-4D18-A64E-ACCFB83EACC7 Val6 2 |
+---------------------------------------------------------+
SELECT A.*
FROM TABLE A,
(
SELECT Col1,MIN(Col3) AS Col3
FROM TABLE
GROUP BY Col1
) B
WHERE A.Col3=B.Col3;
A bit smarter (i think):
SELECT * INTO #TEMP
FROM
(
SELECT 'a72195fa-57ca-4849-b423-5595219c8f6b' col1, 'Val1' col2, 1 col3
UNION SELECT 'a72195fa-57ca-4849-b423-5595219c8f6b' col1, 'Val2' col2, 1 col3
UNION SELECT 'a72195fa-57ca-4849-b423-5595219c8f6b' col1, 'Val3' col2, 2 col3
UNION SELECT 'a72195fa-57ca-4849-b423-5595219c8f6b' col1, 'Val4' col2, 3 col3
UNION SELECT '2F6D0B9E-2221-4D18-A64E-ACCFB83EACC7' col1, 'Val5' col2, 2 col3
UNION SELECT '2F6D0B9E-2221-4D18-A64E-ACCFB83EACC7' col1, 'Val6' col2, 2 col3
UNION SELECT '2F6D0B9E-2221-4D18-A64E-ACCFB83EACC7' col1, 'Val7' col2, 3 col3
) A
SELECT * FROM #TEMP
SELECT *
FROM
(
SELECT *
, RANK() OVER(PARTITION BY col1 ORDER BY col3 ASC) _RANK
FROM #TEMP
) a
WHERE a._RANK = 1
Here is one way using a subquery:
SELECT *
FROM myTable
WHERE Col3 = (SELECT MIN(Col3) FROM myTable WHERE Col1 = #SomePassedInGuid)
AND Col1 = #SomePassedInGuid
Here is basically the same query Lee gave, expressed a bit more compactly.
select top (1) with ties
Col1, Col2, Col3
from T
order by rank() over (
partition by Col1
order by Col3
)