SQL - How to identify permutations of multiple key values - sql

Thank you for reviewing. I'm in desperate need of help and having trouble even being clear on the question below...
Using SQL 2008 I have a table set up with five columns.
Data effectively looks like this:
column1 column2 column3 column4 column5
T1 N1 A1 L1 S1
T1 N2 A2 L2 S4
T1 N2 A3 L2 S2
T1 N2 A1 L2 S4
T2 N6 A3 L3 S2
T2 N7 A3 L3 S4
T2 N7 A3 L4 S4
...
For records that have the same column1 value, I want to identify each unique permutation of column2 through column5.
I want to answer questions like this:
Case 1
How many records exist where
column1 is the same value and
column2 is the same value and
column3 is the same value and
column4 is the same value and
column5 is different
then
Case 2
column1 is the same value and
column2 is the same value and
column3 is the same value and
column4 is different and
column5 is the same value
then
Case 3
column1 is the same value and
column2 is the same value and
column3 is the same value and
column4 is different and
column5 is different
and so on. Thanks!

You can do this in one query, by setting up a table of the permutations you want and some case logic in the query.
Here is an example with three columns.
with t as (
select 'a' as a, 'b' as b, 'c' as c union all
select 'a', 'b', 'd' union all
select 'e', 'b', 'd'
),
perms as (
select 1 as col1, 1 as col2, 1 as col3 union all
select 1, 1, 0 union all
select 1, 0, 0 union all
select 0, 1, 1 union all
select 0, 1, 0 union all
select 0, 0, 1
)
select (case when p.col1 = 1 then a end) as col1,
(case when p.col2 = 1 then b end) as col2,
(case when p.col3 = 1 then c end) as col3,
count(*)
from t cross join
perms p
group by (case when p.col1 = 1 then a end),
(case when p.col2 = 1 then b end),
(case when p.col3 = 1 then c end)

Hmm. If you want to do it by hand, something like group by with multiple keys should do it. E.g. for case 1 you should do something like:
select column1,column2,column3, column4, count(column5) group by column1,column2,column3, column4
This should provide unique records for each unique combination of column1-column4. If you want distinct, then you probably need to do some preprocessing.
If you want a more flexible, probably a store procedure performing a group by could be a solution.

Related

SQL - Update Rows from a list of values

So Table Setup is:
Column1 Column2 Column3
A 1 Null
B 2 Null
C 1 Null
D 2 Null
E 1 Null
F 2 Null
G 1 Null
H 2 Null
I would like to update Column3 with an array of values (Value1, Value2, Value3) and cycle through that list until the update is complete
The ultimate goal is for the table to look like this:
Column1 Column2 Column3
A 1 Value1
B 2 Value2
C 1 Value3
D 2 Value1
E 1 Value2
F 2 Value3
G 1 Value1
H 2 Value2
I originally tried in powershell but it was not working as I would have liked because of how the data is being imported, so now I am looking towards SQL. Any suggestions would be great!
You could try an update join here. The approach below is to assign an ordered sequence to both your original table and the "array" of values for updating. We join using modulus logic, such that your table's sequence ordering will match up the values in the array and will wrap around until all values have been assigned.
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY Column1) rn
FROM yourTable
)
UPDATE t1
SET Column3 = t2.val
FROM cte t1
INNER JOIN
(
SELECT 1 AS id, 'Value1' AS val UNION ALL
SELECT 2, 'Value2' UNION ALL
SELECT 3, 'Value3'
) t2
ON t2.id = 1 + ((t1.rn - 1) % 3);
Demo
Assuming you can put the "array" in a table, you can use something like this:
with vals as (
select v.*,
row_number() over (order by (select null)) - 1 as seqnum,
count(*) over () as cnt
from (values ('Value1'), ('Value2'), ('Value3')) v(val)
)
update t
set t.column3 = v.val
from (select t.*,
row_number() over (order by column1) - 1 as seqnum
from t
) t join
vals v
on t.seqnum % v.cnt = v.seqnum;
The basic idea is to enumerate the rows in each table and then use modulo arithmetic to match them.

How to minus the sum of one query to the sum of another query in the same oracle sql table?

I have 2 queries, both are returning sum, I want the difference between those sums in a single query.
Query 1:
select sum(Records) from my_table where column1 ='1' and column2 = 'abc'
Query 2:
select sum(Records) from my_table where column1 ='2' and column2 = 'adf'
note both queries having same table_name.
My table:
column1 column2 column3 column4 records
1 aa something abc 12
2 bb something acd 25
2 aa something adf 04
1 bb something abc 21
Any help will be appreciated.
Thanks In advance.
You can just use the your existing queries as the columns and take the difference.
with my_table (column1, column2, column3,column4, records) as
( select 1, 'aa', 'something', 'abc', 12 from dual union all
select 2, 'bb', 'something', 'acd', 25 from dual union all
select 2, 'aa', 'something', 'adf', 04 from dual union all
select 1, 'bb', 'something', 'abc', 21 from dual
)
select r1, r2, r1-r2 diff
from (select sum(Records) r1 from my_table where column1 ='1' and column4 = 'abc')
, (select sum(Records) r2 from my_table where column1 ='2' and column4 = 'adf');
Note: I changed the queries to reference column4 instead of column2 in order to match the sample date provided.
Use conditional aggregation:
select sum(case when column1 = '1' and column2 = 'abc' then Records
when column1 = '2' and column2 = 'adf' then - Records
else 0
end) as diff
from my_table ;
Or, if you want to keep queries you've already written, use them as CTEs:
with
a (suma) as
(select sum(Records) from my_table where column1 ='1' and column2 = 'abc'),
b (sumb) as
(select sum(Records) from my_table where column1 ='2' and column2 = 'adf')
select a.suma - b.sumb as difference
from a cross join b
I don't have Oracle handy today but this should get you close.
select ( select sum(Records) from my_table where column1 ='1' and column2 = 'abc') -
(select sum(Records) from my_table where column1 ='2' and column2 = 'adf')
as Total from dual;

Show 2 columns in 2 different rows - SQL

I need to separate two columns into two rows in sql
I have this:
Column1 Column2 Column3
Car 2 5
Boat 4
Truck 6
And I want this:
Column1 Column2
Car 2
Car 5
Boat 4
Truck 6
How can I do this in SQL?
This operation is unpivoting. I would recommend apply:
select t.column1, v.col
from t cross apply
(values (col1), (col2)) v(col)
where v.col is not null;
This should do it
select Column1, Column2
from tbl where Column2 is not null and Column2 <> ''
union
select Column1, Column3
from tbl where Column3 is not null and Column3 <> ''

Move table data from one row to another row if source row is null

I have the table, with some columns contains null values, i tasked to move all the NULL values into left side, so the numeric values are moved from right to left in same order.
(for ex)
Column1 Column2 Column3 Column4
--------------------------------------------
NULL 1 NULL 3
1 NULL 3 2
1 2 3 NULL
Output should be
Column1 Column2 Column3 Column4
--------------------------------------------
1 3 NULL NULL
1 3 2 NULL
1 2 3 NULL
This is a pain, but you can do it using outer apply:
select t.id, v.*
from t outer apply
(select max(case when i = 1 then colval end) as col1,
max(case when i = 2 then colval end) as col2,
max(case when i = 3 then colval end) as col3,
max(case when i = 4 then colval end) as col4
from (select row_number() over (order by colnum) as i, v.*
from (values (1, t.col1), (2, t.col2), (3, t.col3), (4, t.col4)
) v(colnum, colval)
where colval is not null
) v
) v;
I should note that the need to do this type of transformation suggests that you have a poor data model. The values in the separate columns should probably be in another table, with one row per id and per column.

Iterating result of Select Query

I have a question related to select query. here I am explaining down below.
I have a table with the following data
**Column1(Primary Key) Column2 Column3**
------ --------- --------------
1 C
2 C
3 Null
4 H
5 L
6 H
my problem is I have to replace the value of Column3 with the corresponding value of Column1 for every occurrence of data "C", "H" and "L". Please provide me query related to this problem. How can I solve this using query or stored procedure. Please elaborate the same.
I need final select query result as follows
**Column1(Primary Key) Column2 Column3**
------ --------- --------------
1 C 1
2 C 2
3 Null
4 H 4
5 L 5
6 H 6
Select Column1, Column2,
CASE
WHEN Column2 is not null THEN Column1
ELSE null --or whatever value you want for blank
END as Column3
From TableName t1
Alternatively you could it it like this:
Select Column1, Column2,
CASE
WHEN Column2 = 'L' or Column2 = 'H' or Column2 = 'C' THEN Column1
ELSE null --or whatever value you want for blank
END as Column3
From TableName t1
Do you mean UPDATE?
UPDATE tbl SET Column3 = Column1 WHERE Column2 IN ('C', 'H', 'L', 'F')
Or for all;
UPDATE tbl SET Column3 = Column1 WHERE Column2 IS NOT NULL
UPDATE mytable
SET Column3 = Column1
WHERE Column2 in ('C', 'H', 'L')
like this?
select Column1, Column2, Column1 as Column3 from table
Or I'm not sure what you are actually asking for ..?
Ah, sorry. Dind't read all of the question there ...
Most SQL dialects have a way to do conditional subselects, but they are different in differend dialects. So which SQL are you using?