Select dynamic column based on value of another column? - sql

Given the following table, I would like to dynamically select the Name1 or Name2 field based on the value of the WhichName column.
id Name1 Name2 WhichName SomeValue
1 Bob James 1 Blue
2 Steve 2 Horse
3 Fred 1 Radish
The results should look like this:
id Name SomeValue
1 Bob Blue
2 Steve Horse
3 Fred Radish
DBMS is Caché

You can do this with case:
select id,
(case when WhichName = 1 then Name1 else Name2 end) as Name,
SomeValue
from <table>;
Note: if your prefer Name1, unless it is NULL, then you can use COALESCE():
select id, coalesce(Name1, Name2) as Name, SomeValue
from <table>;

Related

Condition filtering SQL

I have a table
Table name - commands
id
name
status
group_id
id - number
name - string
status - 0 or 1
group_id - number
I need to sort as follows: for all elements with the same group_id I have to check if at least one has a status of 1, if so, then leave, if not, then remove such a group and so on for all group_id
I tried to do it through GROUP BY, and then using HAVING to remove unnecessary groups, but this way I don't get the whole table to be displayed or a query that does not work.
I think it should look like:
SELECT COUNT(*) FROM commands GROUP BY group_id HAVING *condition*
Please let me know if there are any other commands to use.
id
name
status
group_id
1
name1
0
1
2
name2
0
1
3
name3
0
2
4
name4
1
2
5
name5
1
2
6
name6
0
3
7
name7
1
4
Result:
id
name
status
group_id
3
name3
0
2
4
name4
1
2
5
name5
1
2
7
name7
1
4
In Postgres, that's a good spot to use a boolean window function:
select *
from (
select t.*, bool_or(status = 1) over(partition by group_id) has_status_1
from mytable t
) t
where has_status_1
bool_or checks if any row in the group satisfies its predicate ; we can use this information for filtering.
The upside is that the table is scanned only once, as opposed to the correlated subquery solution.
You may use EXISTS operator with a correlated subquery as the following:
SELECT id, name, status, group_id
FROM table_name T
WHERE EXISTS(SELECT 1 FROM table_name D WHERE D.group_id = T.group_id AND D.status=1)
ORDER BY id
See a demo.

bigquery - Combine row data with columns of unique data

can this scenario be accomplished with a single query?
read example table and transpose based on id each cat and value.
Existing Table would contain the columns and or null columns are created when
select is done (e.gl NULL Att1_Val1)
Example Table Existing Table
id name cat value ID Name Att1_Val1 Att2_Val1 Att3_Val1 Att4_Val1
1 name1 att1 1 1 Name1 1 2 3 Null
1 name1 att2 2 1 Name2 4 5 6 7
1 name1 att3 3
2 name2 att1 4
2 name2 att2 5
2 name2 att3 6
2 name2 att4 7
See snapshot for a Better view of tables
I resolved this for my real table structure (names in the example where changed and I also had a case statement. But this is the basic of how I solved.
Select id, Name, Att1, Att2, Att3, Att4
FROM (SELECT id, value, att FROM 'List_table' as Source_Table)
PIVOT
(MAX(Value) FOR att
IN ('Att1', 'Att2', 'Att3','Att4'))
AS Pivot_table

I'm trying to achieve below result output

can we get the below desired table by using PIVOT or something. I'm trying to convert below table to the desired output like below.
Data Set:
question_id element_id
1 john
1 bran
1 o_siera
2 brook
2 joseph
2 o_daniel
2 o_cody
3 derick
3 james
3 sophia
3 o_sandra
3 o_ashley
Desired Result:
question_id element_id element
1 john o_siera
1 bran o_siera
2 brook o_daniel
2 joseph o_daniel
3 derick o_sandra
3 james o_sandra
3 sophia o_sandra
OR
OR can we achieve it in this way
question_id element_id element
1 john o_siera
1 bran
2 brook o_daniel,o_cody
2 joseph
3 derick o_sandra, o_ashley
3 james
3 sophia
Its not an ideal data model. Something like this should work except when a value that begins with 'o_%' is an element_id and not an element.
This was not tested.
select t1.question_id
,case when t1.element_id not like 'o_%' then t1.element_id else '' end element_id
,case when t2.element_id like 'o_%' then t2.element_id else '' end element
from table t1
join table t2 on t1.question_id=t2.question_id
I would suggest:
select t.*, max_o
from (select t.*,
max(case when element_id like 'o\_%' then element_id end) over (partition by question_id) as max_o
from t
) t
where element_id not like 'o\_%';

postgresql statement prob

I have two table A and B as following.
A:
key type
0 t
1 f
2 t
3 f
4 t
5 t
.......
B:
key name
0 Mary
0 Tony
0 Krolik
1 Tom
2 Tony
3 Tony
3 Mary
3 Tom
4 Tony
4 Tim
5 Tim
5 Mary
5 Wuli
.....
I hope to find top n occurence name that it's type is 'f'.
For example, in A, the type of key 1 and 3 are 'f', we find key 1 and 3 in table B, there are 2 'Tom' and 1 'Mary' and 1 'Tony'.
1 Tom
3 Tony
3 Mary
3 Tom
if n = 1 and the table is just showed as before, we hope to get 'Tom', because its occurence is top 1.
How can I write sql statement to satisfy these requirement?
I write something like below, but it is wrong. Can anyone help me? I assume n = 20.
SELECT DISTINCT TOP 20 name
FROM B
WHERE key IN (
SELECT key
FROM A
WHERE "type" = 'f'
)
GROUP BY name
ORDER BY DESC;
You don't seem to need aggregation. And the equivalent of top in Postgres is limit or fetch first <row> rows:
SELECT name, key
FROM B
WHERE B.key IN (SELECT A.key
FROM A
WHERE "type" = 'f'
)
ORDER BY key;
This corresponds to the results presented in the question. Your description doesn't quite match those results.

Select multiple records as multiple columns in SQL

I have a table that look like this:
ID Name
-------
1 John
1 Mary
1 Jane
2 John
2 Mary
3 Jane
Knowing that every ID can only contain up to three names, I want to use a SELECT statement to turn this into the following:
ID Name1 Name2 Name3
--------------------
1 John Mary Jane
2 John Mary
3 Jane
Is there a way to do this in SQL?
If you know that there are at most three names, you can do this using conditional aggregation:
select id,
max(case when seqnum = 1 then name end) as name1,
max(case when seqnum = 2 then name end) as name2,
max(case when seqnum = 3 then name end) as name3
from (select t.*, row_number() over (partition by id order by name) as seqnum
from table t
) t
group by id;
With Oracle, you can use the PIVOT feature.
However, you'll need to RANK your rows first, over id-name pairs, and then you can do the pivot directive for (literally) the rank you just generated.
Pages to read:
http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html
http://www.oracle-developer.net/display.php?id=506