Get none null column row and other row when its null - sql

I have a problem and I wondered if I can do it only with sql.
So I have a table named: tbl, and columns a, b, c which a and b rows aren't null and c can be null, for example:
a
b
c
a1
b1
NULL
a2
b2
c2
a3
b3
NULL
And I wish to get the result with columns a and x when x is defined: take from b when c is null and take from c if its not null, so the output will be:
a
col2
a1
b1
a2
c2
a3
b3
There is a sql command which can do the above?
Thanks

You can use the COALESCE function, given that your DBMS supports it.
SELECT a,
COALESCE(c, b)
FROM tab

If your DBMS does not support the functions from answers above, you can do it with CASE function:
SELECT
a,
CASE
WHEN c IS NULL THEN b
ELSE c
END AS col2
FROM
tbl

You can use
select a, nvl(c, b) from table;

Related

Select entries that have non repeating values on a specific column (although other columns may have repeating or non repeating values) (SQL)

Let's say I have the following table:
A
B
C
D
a1
b1
c1
d1
a1
b1
c1
d2
a2
b2
c3
d3
a2
b2
c4
d3
I want to filter and see all four columns for entries that have the same value con column A but different on column C, so I get only this as a result:
A
B
C
D
a2
b2
c3
d3
a2
b2
c4
d3
I don't really care if values con columns B and D are the same or different, although I would like to have them in my table to do further analysis later.
Using the DISTINCT statement would give me all the columns as a result, as they all are different in some column, so that doesn't work for me.
I read some questions (like this one) and the answers recommended using the row_number() over(partition by...) clause, although the use they gave it doesn't quite fit my problem (I think), as it would also return the first row with a repeating value on column C.
Any ideas how this could be done?
You can use exists:
select t.*
from t
where exists (select 1
from t t2
where t2.a = t.a and t2.c <> t.c
)
order by t.a;
You could use a self join
select t1.*
from t t1
join t t2 on t1.a=t2.a and t1.c<>t2.c

SQL - Merge / Update & Delete from existing rows

Given the following table:
A B C D E
a1 b1 NULL NULL e1
NULL NULL c1 d1 NULL
a1 b1 c1 NULL NULL
I want to run a query that would merge/update&delete the existing rows whenever at least one of the columns have a equal value (except when NULL = NULL) to result in the following table:
A B C D E
a1 b1 c1 d1 e1
Please note that there are no unique IDs in any of the columns as any could have NULL values.
Could you please assist?
Edited:
If any of the columns do not share the same value, I would them to be a separate record; and this would not affect any other records.
For example, if row 3 was:
A B C D E
a1 b1 c1 NULL e2
then the desired output would be:
A B C D E
a1 b1 NULL NULL e1
a1 b1 c1 d1 e2
since row 1 already has a e1 <> e2 (so is left as a separate record); and row 2 and 3 are merged since they share c1 as a common C value AND also does not have any columns with differing values (other than NULLS).
Another example:
If there was an additional row, row 4 (with the original table):
A B C D E
NULL NULL c1 d2 NULL
Then the desired output would be:
A B C D E
a1 b1 c1 d1 e1
a1 b1 c1 d2 e1
This isn't really a complete answer, but rather an answer that will help others understand the problem and hopefully help steer them in the right direction to provide the complete answer:
As I understand it, the fundamental problem with the scenario you describe is that we need something like TRANSACTION (but probably not TRANSACTION) which will somehow allow us to accomplish the following steps.
Step 1.
In the following table, take the first row and compare it to all the other rows.
A B C D E
a1 b1 NULL NULL e1
NULL NULL c1 d1 NULL
a1 b1 c1 NULL NULL
For the first row, we find a match with the third row in column [A] and then we update columns [B], [C], [D], and [E], then we delete the third row - giving us the following table:
A B C D E
a1 b1 c1 NULL e1
NULL NULL c1 d1 NULL
Step 2
We look at column [B] and find no matches.
Step 3
We look at column [C] and find a match so we update the current row (row 1). We are ignoring / not merging NULLs so we get the following table
A B C D E
a1 b1 c1 d1 e1
The problem with this is that MERGE operations do not work as described. By that I mean once a row is MERGED, we move onto the next row.
This is a fairly complicated process so I personally am not sure how to tackle it, just wanted to help explain the problem in a more "developer-friendly" way.
I would expect the answer to look something like this (I don't think you can actually use isnull in the ON clause):
MERGE Table2 AS target
USING Table1 as source
ON (isnull(target.[A], -1) = isnull(source.[A], -2) OR isnull(target.[B], -1) = isnull(source.[B], -2), etc.... )
WHEN MATCHED
THEN UPDATE
SET target.[A] = source.[A]
and so on...

SQL complex query for three fields

I have a table with this structure:
Field A Field B Field C
a1 b1 t1
a1 b1 t2
a2 b1 t1
a2 b1 t2
Field A and Field B are related, in a way that there are several a* for a given b*.
I need to list either Field A or Field B that meet the following criteria:
b* has several a*
a* has 1 to N t*
if two a* belonging to the same b* have different t*, then I need to list that a* or its parent b*
In the previous example, nothing whould be listed because b1 has a1 and a2, and both a1 and a2 have the same information: they both have t1 and t2.
In the next example, I need to detect that a1 and a2, belonging to b1, have different information (a1: t1 and t2; b1: only t1, it doesn't have t2).
Field A Field B Field C
a1 b1 t1
a1 b1 t2
a2 b1 t1
a3 b2 t3
The query would show either a1, a2 or b1.
I know this is complicated but I need to get that information.
Thanks!
You actually need to add the explanation to why there's nothing returned in the first example to the requirements.
Solution to example 1:
SELECT
t.B,
GROUP_CONCAT(DISTINCT t.A)
FROM
t
INNER JOIN (
SELECT
B,
A
FROM
t
GROUP BY B, A
HAVING
COUNT(DISTINCT C) > 1
) q ON t.A = q.A AND t.B = q.B /* a* has 1 to N t* */
WHERE t.B IN (
SELECT sq.B FROM (
SELECT st.B, GROUP_CONCAT(st.C ORDER BY st.C) AS gcc FROM t AS st GROUP BY st.B, st.A
) sq GROUP BY sq.B HAVING COUNT(DISTINCT gcc) > 1
) /* if two a* belonging to the same b* have different t*, then I need to list that a* or its parent b* */
GROUP BY t.B
HAVING
COUNT(DISTINCT t.A) > 1 /* b* has several a* */
;
play around with it if you want in this sqlfiddle
Your second example is not clear to me. But I guess you mean this:
SELECT
B, A
FROM
t
WHERE A IN ('a1', 'a2')
GROUP BY B, A
HAVING
COUNT(DISTINCT C) > 1
OR
COUNT(*) = 1;
sqlfiddle for Example 2

Finding Permutations of columns in SQL

I have a reference data table having columns as codes and values.
For e.g. there are three code types viz. A, B, C.
The table is as below:
Code Value
---------------------
A1 a_one
A2 a_two
B1 b_one
B2 b_two
B3 b_three
C1 c_one
C2 c_two
C3 c_three
C4 c_four
---------------------
I have a requirement where the input will be code types and output should be all permutations between the input code types.
For e.g. if the input code types are A and C, the output of my sql should be:
col_1 col_2
---------------------
A1 C1
A1 C2
A1 C3
A1 C4
A2 C1
A2 C2
A2 C3
A2 C4
---------------------
Similarly if the input code types is A, B, C, the output of the sql will have three columns with all the permutations between A, B, C viz. A1 B1 C1 to A2 B3 C4.
I have no idea how to start on this. So any hints will be useful.
Thanks for reading!
If I understand your question correctly, this is one of those rare cases where a CROSS JOIN is actually what you want. A CROSS JOIN will give you the Cartesian product of two sets, which means all possible combinations between the values in those sets.
Example:
Table A with column 1 contains values 'a' and 'b'
Table B with column 2 contains values 'c' and 'd'
The following CROSS JOIN query (note there is no 'join condition' specified, on purpose):
SELECT *
FROM A
CROSS JOIN B
will return the following result:
1 2
--------
a c
a d
b c
b d
I created an SQL Fiddle to show you a possible solution. You can tweak it a bit to see if this is what you need. (Note it's an Oracle fiddle, as there is no DB2 option.)

DB Sorting Challenge

I have a table as follows,
A A
B B1
A A1
B B
A A2
B B3
A A3
B B2
My result set should be,
A A
A A1
A A2
A A3
B B
B B1
B B2
B B3
Note: A, A1 are all GUIDs.
I have tried quite a few tricks. Please help me solve this problem.
I'm assuming that the spaces indicate separate columns.
select * from [Table] order by [column1], [column2]
If each line is a string then doing an order by [column1] should be sufficient.
Maybe I am missing something, but I figured this would be:
ORDER BY Column1, Column2
Perhaps you could explain this further?