get row and column depending on value using SQL? [duplicate] - sql

This question already has answers here:
Unpivot with column name
(3 answers)
Closed 4 years ago.
I got a couple of tables with rows and columns. In some there is an X and in some not. Now I would like to get all row-column pairs that have an X in there.
Is that possible with SQL? Would it be possible with somehow else?
One idea I had was using case, but I would need to hard code all the col/row combinations.
Example
Table:
rowNo| col1 | col2 | colN
-----|------|------|----
row1 | X | |
row2 | X | X |
rowN | | |
Expected result:
| row | col |
| ----|---- |
| row1|col1 |
| row2|col1 |
| row2|col2 |

You can use union all :
select t.rowno, t.col
from ( select rowno, col1 as col
from table t
union all
select rowno, col2
from table t
. . .
) t
where col = 'X';
If you are working with SQL Server, then you can apply :
select t.rowNo as row, tt.col
from table t cross apply
( values (col1), (col2), . . . ,(coln)
) tt(col)
where tt.col = 'X';

Related

Remove Duplicates from table such that if A|B exists then B|A doesn't exist - SQL [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 11 months ago.
Improve this question
You are given a table which looks like this:
| COL1 | COL2 |
===============
| A | B |
| B | A |
| C | B |
| B | C |
The question is to remove duplicate rows, i.e., if a row = | A | B | exists then we cannot have another row = | A | B | or even a row = | B | A |.
So the result should look something like this:
| COL1 | COL2 |
===============
| A | B |
| C | B |
I am unable to think of a way to implement this in one query or even with a series of SQL queries.
Thanks.
Several ways. Here are a couple:
Standard SQL:
SELECT DISTINCT
CASE WHEN col1 < col2 THEN col1 ELSE col2 END AS col1
, CASE WHEN col1 < col2 THEN col2 ELSE col1 END AS col2
FROM tbl
;
or (MySQL supports this one):
SELECT DISTINCT
LEAST(col1, col2) AS col1
, GREATEST(col1, col2) AS col2
FROM tbl
;
There are other approaches, which have slightly different behavior.
For instance, we might want to keep ('B', 'A') if ('A', 'B') doesn't also exist.
Another thought is we could prevent this issue by correcting the data on INSERT by using similar LEAST / GREATEST logic in the INSERT (or a trigger), to be sure col1 was always less than or equal to col2.
Then add a unique constraint on (col1, col2) and a table check constraint (col1 <= col2) to prevent duplicates and reflections.
select distinct least(col_1, col_2), greatest(col_1, col_2)
from the_table
order by 1

How to convert same column different rows to different column same row in SQL?

This is what I want to do.
----input table----
SID | VALUE
1 | v1
1 | v2
1 | v3
1 | v4
1 | v5
2 | s1
2 | s2
2 | s3
---output table----
sid | col1 | col2 | col3 | col4 | col5
1 | v1 | v2 | v3 | v4 | v5
2 | s1 | s2 | s3 | '' | ''
The general pattern of a conditional aggregation:
SELECT
sid,
MAX(CASE WHEN value = 'v1' THEN value END) as col1,
MAX(CASE WHEN value = 'v2' THEN value END) as col2,
...
FROM t
GROUP BY sid
Il leave it for you to put the other columns in as a practice:)
I prefer to put the value as the column name, not col1, col2 etc
Also if you really want empty strings rather than nulls for those last two columns you can modify the case when to have ELSE '' (note: won't work if you use MIN instead of max) or use COALESCE around the MAX
Learn pivot
https://learn.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-ver15
do something like
select *
from
(
select sid, value
from table_name
) src
pivot
(
sid
for sid in ([1], [2])
) piv;

Sybase, SQL: Adding a counter to duplicate values

I try to handle the following case. I have a list of entries in the db:
Col 1 | Col 2|
------|------|
aaaa | x |
aaaa | x |
bbbb | y |
cccc | z |
cccc | z |
The goal is to identify the duplicates in Col 1 and add a number to each line and for the duplicates the number should incremented so that we get also unique entries. After each new entry the counter should start from 1 again.
Col 1 | Col 2 |
--------|-------|
aaaa-1 | x |
aaaa-2 | x |
bbbb-1 | y |
cccc-1 | z |
cccc-2 | z |
Do you have any idea how to manage this?
Best regards,
Dirk
Hi Dirk,
WITH cte
AS (SELECT Col1,Col2,ROW_NUMBER() OVER (PARTITION BY Col1,Col2
ORDER BY ( SELECT 0)) RN
FROM tableName)
select Col1+'-'+convert(varchar,rn) as Col1,Col2 FROM cte
Thanks :)
I would try this. I hope that solves your issue.
SELECT COL1 + ' - ' + ROW_NUMBER() OVER(PARTITION BY COL1 ORDER BY COL1) as COL_A
, COL2 AS COL_B
FROM TABLE
Depending on the DBMS you are working with, you might have to CAST ROW_NUMBER(). I tried that on Oracle 11.2 and it worked properly:
SELECT COL1 || ' - ' || ROW_NUMBER() OVER(PARTITION BY COL1 ORDER BY COL1) AS COL_A
, COL2 AS COL_B
FROM TABLENAME

SQL rank/dense_rank and how to query/calculate with the result

So I have a table where it dense_ranks my rows.
Here is the table:
COL1 | COL2 | COL3 | DENSE_RANK |
a | b | c | 1 |
a | s | r | 1 |
a | w | f | 1 |
b | b | c | 2 |
c | f | r | 3 |
c | q | d | 3 |
So now I want to select any rows where the rank was only represented once, so the 2 is all alone, but not the 1 or 3. I want to select all the rows where this occurs, but how do I do that?
Some ideas:
-COUNT DISTINCT (RANK())
-COUNT RANK()
but neither of those are working, any ideas? please and thank you!
happy hacking
actual code:
SELECT events.event_type AS "event",
DENSE_RANK() OVER (ORDER BY bw_user_event.pad_id) as rank
FROM user_event
WHERE (software_events.software_id = '8' OR software_events.software_id = '14')
AND (software_events.event_type = 'install')
WITH Dense_ranked_table as (
-- Your select query that generates the table with dense ranks
)
SELECT DENSE_RANK
FROM Dense_ranked_table
GROUP BY DENSE_RANK
HAVING COUNT(DENSE_RANK) = 1;
I don't have SQL Server to test this. So please let me know whether this works or not.
I would think you can add a COUNT(*) OVER (PARTITION BY XXXXX) where XXXXX is what you include in your dense rank.
Then wrap this in a Common Table Expression and select where your new Count is = 1.
Something like this fiddler:
http://sqlfiddle.com/#!6/ae774/1
Code included here as well:
CREATE TABLE T
(
COL1 CHAR,
COL2 CHAR,
COL3 CHAR
);
INSERT INTO T
VALUES
('a','b','c'),
('a','s','r'),
('a','w','f'),
('b','b','c'),
('c','f','r'),
('c','q','d');
WITH CTE AS (
SELECT COL1 ,
COL2 ,
COL3,
DENSE_RANK() OVER (ORDER BY COL1) AS DR,
COUNT(*) OVER (PARTITION BY COL1) AS C
FROM dbo.T AS t
)
SELECT COL1, COL2, COL3, DR
FROM CTE
WHERE C = 1
Would return just the
b, b, c, 2
row from your test data.

Rotate one column and Select it comma seperated [duplicate]

This question already has answers here:
Inner Join Two Table, aggregating varchar fields
(2 answers)
Closed 8 years ago.
I have a table like this:
PK | COL1 | COL2
----------------
1 | A | a
2 | B | b
3 | C | c
4 | A | d
5 | A | e
6 | B | f
7 | C | g
8 | C | h
and I want to do an Select that I get the following result
COL1 | COL2
---------------
A | a,d,e
B | b,f
C | c,g,h
As I understand SQL at the moment I don't know how to do this without "programing" something extra e.q. with PL/SQL
But i search for an DBMS independent solution as good as it can be DBMS independent.
This is an Oracle (11.2) solution:
select col1,
listagg(col2, ',') within group (order by col1) as col2
from the_table
group by col1;
As you need this for other DBMS as well, this would be the Postgres solution:
select col1,
string_agg(col2, ',' order by col1) as col2
from the_table
group by col1;
For MySQL this would be:
select col1,
group_concat(col2 ORDER BY col1 SEPARATOR ',') as col2
from the_table
group by col1;
For a SQL Server solution, see Vijaykumar's answer.
try this !!
SELECT [col1],
SUBSTRING(d.col2,1, LEN(d.col2) - 1) col2
FROM
(
SELECT DISTINCT [col1]
FROM table1
) a
CROSS APPLY
(
SELECT [col2] + ', '
FROM table1 AS b
WHERE a.[col1] = b.[col1]
FOR XML PATH('')
) d (col2)