Split Microsoft SQL Row - sql

Assume I have data like so:
+------+------+------+------+
| Col1 | Col2 | Col3 | Col4 |
+------+------+------+------+
| a | b | x | y |
+------+------+------+------+
I wish to split it after a certain column to achieve something like this:
+------+------+
| Col1 | Col2 |
+------+------+
| a | b |
| x | y |
+------+------+
What would be the easiest way to achieve this? I am currently forced to do this in an old MS Access database with a connection to the SQL server. Thoughts?

Use union all:
select col1, col2
from t
union all
select col3, col4
from t;
Both databases support union all. Both will take the column names from the first subquery.

Try this,
select col1 as Col1 , col2 as Col2
from t
union all
select col3 as Col1, col4 as Col2
from t;

Related

Oracle group by only ONE column

I have a table in Oracle database, which have 40 columns.
I know that if I want to do a group by query, all the columns in select must be in group by.
I simply just want to do:
select col1, col2, col3, col4, col5 from table group by col3
If I try:
select col1, col2, col3, col4, col5 from table group by col1, col2, col3, col4, col5
It does not give the required output.
I have searched this, but did not find any solution. All the queries that I found using some kind of Add() or count(*) function.
In Oracle is it not possible to simply group by one column ?
UPDATE:
My apologies, for not being clear enough.
My Table:
+--------+----------+-------------+-------+
| id | col1 | col2 | col3 |
+--------+----------+-------------+-------+
| 1 | 1 | some text 1 | 100 |
| 2 | 1 | some text 1 | 200 |
| 3 | 2 | some text 1 | 200 |
| 4 | 3 | some text 1 | 78 |
| 5 | 4 | some text 1 | 65 |
| 6 | 5 | some text 1 | 101 |
| 7 | 5 | some text 1 | 200 |
| 8 | 1 | some text 1 | 200 |
| 9 | 6 | some text 1 | 202 |
+--------+----------+-------------+-------+
and by running following query:
select col1, col2, col3 from table where col3='200' group by col1;
I will get the following desired Output:
+--------+----------+-------------+-------+
| id | col1 | col2 | col3 |
+--------+----------+-------------+-------+
| 2 | 1 | some text 1 | 200 |
| 3 | 2 | some text 1 | 200 |
| 7 | 5 | some text 1 | 200 |
+--------+----------+-------------+-------+
Long comment here;
Yeah, you can't do that. Think about it... If you have a table like so:
Col1 Col2 Col3
A A 1
B A 2
C A 3
And you're grouping by only Col2, which will group down to a single row... what happens to Col1 and Col3? Both of those have 3 distinct row values.
How is your DBMS supposed to display those?
Col1 Col2 Col3
A? A 1?
B? 2?
C? 3?
This is why you have to group by all columns, or otherwise aggregate or concatenate them. (SUM(),MAX(), MIN(), etc..)
Show us how you want the results to look and I'm sure we can help you.
Edit - Answer:
First off, thanks for updating your question. Your query doesn't have id but your expected results do, so I will answer for each separately.
Without id
You will still need to group by all columns to achieve what you're going for. Let's walk through it.
If you run your query without any group by:
select col1, col2, col3 from table where col3='200'
You will get this back:
+----------+-------------+-------+
| col1 | col2 | col3 |
+----------+-------------+-------+
| 1 | some text 1 | 200 |
| 2 | some text 1 | 200 |
| 5 | some text 1 | 200 |
| 1 | some text 1 | 200 |
+----------+-------------+-------+
So now you want to only see the col1 = 1 row once. But to do so, you need to roll all of the columns up, so your DBMS knows what do to with each of them. If you try to group by only col1, you DBMS will through an error because you didn't tell it what to do with the extra data in col2 and col3:
select col1, col2, col3 from table where col3='200' group by col1 --Errors
+----------+-------------+-------+
| col1 | col2 | col3 |
+----------+-------------+-------+
| 1 | some text 1 | 200 |
| 2 | some text 1 | 200 |
| 5 | some text 1 | 200 |
| ? | some text 1?| 200? |
+----------+-------------+-------+
If you group by all 3, your DBMS knows to group together the entire rows (which is what you want), and will only display duplicate rows once:
select col1, col2, col3 from table where col3='200' group by col1, col2, col3
+----------+-------------+-------+
| col1 | col2 | col3 |
+----------+-------------+-------+
| 1 | some text 1 | 200 |
| 2 | some text 1 | 200 | --Desired results
| 5 | some text 1 | 200 |
+----------+-------------+-------+
With id
If you want to see id, you will have to tell your DBMS which id to display. Even if we group by all columns, you won't get your desired results, because the id column will make each row distinct (They will no longer group together):
select id, col1, col2, col3 from table where col3='200' group by id, col1, col2, col3
+--------+----------+-------------+-------+
| id | col1 | col2 | col3 |
+--------+----------+-------------+-------+
| 2 | 1 | some text 1 | 200 | --id = 2
| 3 | 2 | some text 1 | 200 |
| 7 | 5 | some text 1 | 200 |
| 8 | 1 | some text 1 | 200 | --id = 8
+--------+----------+-------------+-------+
So in order to group these rows, we need to explicitly say what to do with the ids. Based on your desired results, you want to choose id = 2, which is the minimum id, so let's use MIN():
select MIN(id), col1, col2, col3 from table where col3='200' group by col1, col2, col3
--Note, MIN() is an aggregate function, so id need not be in the group by
Which returns your desired results (with id):
+--------+----------+-------------+-------+
| id | col1 | col2 | col3 |
+--------+----------+-------------+-------+
| 2 | 1 | some text 1 | 200 |
| 3 | 2 | some text 1 | 200 |
| 7 | 5 | some text 1 | 200 |
+--------+----------+-------------+-------+
Final thought
Here were your two trouble rows:
+--------+----------+-------------+-------+
| id | col1 | col2 | col3 |
+--------+----------+-------------+-------+
| 2 | 1 | some text 1 | 200 |
| 8 | 1 | some text 1 | 200 |
+--------+----------+-------------+-------+
Any time you hit these, just think about what you want each column to do, one at a time. You will need to handle all columns any time you do grouping or aggregates.
id, you only want to see id = 2, which is the MIN()
co1, you only want to see distinct values, so GROUP BY
col2, you only want to see distinct values, so GROUP BY
col3, you only want to see distinct values, so GROUP BY
maybe analytic functions is what you need
try smth like this:
select col1, col2, col3, col4, col5
, sum(*) over (partition by col1) as col1_summary
, count(*) over () as total_count
from t1
if you google the article - you find thousands on examples
for example this
Introduction to Analytic Functions (Part 1)
Why do you want to GROUP BY , wouldn't you want to ORDER BY instead?
If you state an English language version of the problem you are trying to solve (i.e. the requirements) it would be easier to be more specific.
I guess,maybe you need upivot function
or post your specific final result you want
select col3, col_group
from table
UNPIVOT ( col_group for value in ( col1,col2,col4,col5))
SELECT * FROM table
WHERE id IN (SELECT MIN(id) FROM table WHERE col3='200' GROUP BY col1)

SQL Create dynamic column

I am seeking some help to build an SQL to obtain certain results.
Below are two tables.
Table 1
Col1 | Col2 | Col3 | Col4
----------------------------------------
TESTPC01 | 14/08/2014 | ABCD | CXYZ
TESTPC02 | 14/08/2014 | EFGH | IJKL
Table2
COl1 | Col2 | Col3 | Col4
----------------------------------------
TESTPC01 | 14/08/2014 | ENT | DOC
RESULT
COl1 | Col2 | Col3 | Col4 | Col5 | Col6
-------------------------------------------------------
TESTPC01 | 14/08/2014 | ENT | DOC | ABCD | YES |
TESTPC02 | 14/08/2014 | EFGH | NULL | NULL | NO |
Yes only when there is data for that particular Col3 value is populated in the Table 2 for that specific matching Table1.Col1 = Table2.Col1.
If above condition fails then NO
I could build the SQL using simple select statements but no able to achieve to create the col6 dynamically.
Can any one please guide me how to achieve this?
You want a left outer join with a conditional expression:
select t2.col1, t2.col2, t2.col3,
(case when t1.col1 is not null then t2.col4 end) as col4
t1.col3 as col5,
(case when t1.col1 is null then 'Yes' else 'No' end) as col6
from table2 t2 left join
table1 t1
on t2.col1 = t1.col1 and t2.col2 = t1.col1;
It is unclear to me why col4 would be NULL when there is no match. Usually, you would keep all values from the first table. However, that is how you have specified the results.

SQL query, generating several rows by a value in a field

I am using Oracle database. Imaging I have a table with a row as following
col1 | col2 | col3
'Str1' | 'Str2' | 4
The value from col3=4 should generate 4 rows as following:
col1 | col2 | col3
'Str1' | 'Str2' | 1
'Str1' | 'Str2' | 2
'Str1' | 'Str2' | 3
'Str1' | 'Str2' | 4
After several hours in front of the screen and stil no luck - how can I create such a select query???
You can do this if you create a sequence of integers. Here is an approach:
with seq as (
select level n from dual connect by level <= 100
)
select t.col1, t.col2, seq.n
from t join
seq
on seq.n <= t.col3

SQL query to group a column and ignore null values

I have a table like:
Col1 Col2 Col3 Col4
1 a
1 b
1 c
2 e
2 f
2 g
I need to write a query which will have the output like this
Col1 Col2 Col3 Col4
1 a b c
2 e f g
I am using oracle 10g
If you only have one value per column, then you might be able to use an aggregate function:
select
col1,
max(col2) col2,
max(col3) col3,
max(col4) col4
from yourtable
group by col1
See SQL Fiddle with Demo
The result is:
| COL1 | COL2 | COL3 | COL4 |
-----------------------------
| 1 | b | a | c |
| 2 | e | f | g |

SQL select distinct rows

I have data like this (col2 is of type Date)
| col1 | col2 |
------------------------------
| 1 | 17/10/2007 07:19:07 |
| 1 | 17/10/2007 07:18:56 |
| 1 | 31/12/2070 |
| 2 | 28/11/2008 15:23:14 |
| 2 | 31/12/2070 |
How would select rows which col1 is distinct and the value of col2 is the greatest. Like this
| col1 | col2 |
------------------------------
| 1 | 31/12/2070 |
| 2 | 31/12/2070 |
SELECT col1, MAX(col2) FROM some_table GROUP BY col1;
select col1, max(col2)
from table
group by col1
i reckon it would be
select col1, max(col2)
from DemoTable
group by col1
unless i've missed something obvious
select col1, max(col2) from MyTable
group by col1
SELECT Col1, MAX(Col2) FROM YourTable GROUP BY Col1
In Oracle and MS SQL:
SELECT *
FROM (
SELECT t.*, ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col2 DESC) rn
FROM table t
) q
WHERE rn = 1
This will select other columns along with col1 and col2