SQL QUERY Append Two Columns [duplicate] - sql

This question already has answers here:
MySQL - Split two columns into two different rows
(3 answers)
Closed 7 months ago.
I am still learning on SQL Statements
How do I append two columns?
E.g
Table 1
| ID | Name | Position |
------------------------------
| 1 | Mike | Developer
| 2 | Mark | QA |
Expected Result
Table 2
| ID | User Role/Name |
-----------------------
| 1 | Mike |
| 1 | Developer |
| 2 | Mark |
| 2 | QA |
-----------------------

Use union all:
select ID, Name as "User Role/Name" from table1
union all
select ID, position from table1
order by ID
DEMO

Do you means that it will output like it?
select ID, concat(Position,'/',Name) from Table2
| ID | User Role/Name |
-----------------------
| 1 | Developer/Mike |
| 2 | QA/Mark |

Related

More efficient way to SELECT rows from PARTITION BY

Suppose I have the following table:
+----+-------------+-------------+
| id | step_number | employee_id |
+----+-------------+-------------+
| 1 | 1 | 3 |
| 1 | 2 | 3 |
| 1 | 3 | 4 |
| 2 | 2 | 3 |
| 2 | 3 | 4 |
| 2 | 4 | 5 |
+----+-------------+-------------+
My desired results are:
+----+-------------+-------------+
| id | step_number | employee_id |
+----+-------------+-------------+
| 1 | 1 | 3 |
| 2 | 2 | 3 |
+----+-------------+-------------+
My current solution is:
SELECT
*
FROM
(SELECT
id,
step_number,
MIN(step_number) OVER (PARTITION BY id) AS min_step_number,
employee_id
FROM
table_name) AS t
WHERE
t.step_number = t.min_step_number
Is there a more efficient way I could be doing this?
I'm currently using postgresql, version 12.
In Postgres, I would recommend using distinct on to adress this greatest-n-per-group problem:
select distinct on (id) t.*
from mytbale t
order by id, step_number
This Postgres extension to the SQL standard has usually better performance than the standard approach using window functions (and, as a bonus, the syntax is neater).
Note that this assumes unicity of (id, step_number) tuples: otherwise, the results might be different than those of your query (which allows ties, while distinct on does not).

How to merge columns and transpose in SQL?

I'm working with a custom DBMS (compliant with SQL 2011 Standard), and am trying to combine multiple columns into a single column like so, but am struggling with the syntax:
Current table:
------------------------------------------
| ID | setting_A | setting_B | setting_C |
------------------------------------------
| 1 | ON | OFF | UNKNOWN |
------------------------------------------
Desired query output:
------------------------------
| ID | Setting | Value |
------------------------------
| 1 | A | ON |
------------------------------
| 1 | B | OFF |
------------------------------
| 1 | C | UNKNOWN |
------------------------------
I've tried various IF and CASE statements, but have hit a wall. Any help would be appreciated.
You can unpivot with union all:
select id, 'A' setting, setting_A value from mytable
union all select id, 'B', setting_B from mytable
union all select id, 'C', setting_C from mytable
This assumes that setting_A, setting_B and setting_C are of the same datatype (otherwise, you need conversions to align the datatypes before combining the resultsets).
Demo on DB Fiddle:
id | setting | value
-: | :------ | :------
1 | A | ON
1 | B | OFF
1 | C | UNKNOWN

Window functions limited by value in separate column

I have a "responses" table in my postgres database that looks like
| id | question_id |
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
I want to produce a table with the response and question id, as well as the id of the previous response with that same question id, as such
| id | question_id | lag_resp_id |
| 1 | 1 | |
| 2 | 2 | |
| 3 | 1 | 1 |
| 4 | 2 | 2 |
| 5 | 2 | 4 |
Obviously pulling "lag(responses.id) over (order by responses.id)" will pull the previous response id regardless of question_id. I attempted the below subquery, but I know it is wrong since I am basically making a table of all lag ids for each question id in the subquery.
select
responses.question_id,
responses.id as response_id,
(select
lag(r2.id, 1) over (order by r2.id)
from
responses as r2
where
r2.question_id = responses.question_id
)
from
responses
I don't know if I'm on the right track with the subquery, or if I need to do something more advanced (which may involve "partition by", which I do not know how to use).
Any help would be hugely appreciated.
Use partition by. There is no need for a correlated subquery here.
select id,question_id,
lag(id) over (partition by question_id order by id) lag_resp_id
from responses

Joining tables in oracle

I have a master data table like this:
tableA
ID | tainfo1 | tainfo2
----------------------
1 | me | 100
2 | you | 200
3 | they | 300
and an attribute table like that:
tableB:
ID | type | tbinfo1 | tbinfo2
------------------------------
1 | 1 | good | 7
1 | 2 | bad | 5
2 | 2 | so&so | 6
3 | 1 | awesome | 10
In the attribute table i have a very small set of type and I would like to know if there's any chance to make data output like this.
ID | tainfo1 | tainfo2 | tbinfo1_type1 | tbinfo2_type1 | tbinfo1_type2 | tbinfo2_type2
-----------------------------------------------------------------------------------------
1 | me | 100 | good | 7 | bad | 5
2 | you | 200 | | | so&so | 6
3 | they | 300 | awesome | 10 | |
if all the attributes exists, all the columns are filled, like the record 1, also the _typeX column will appear blanks, like the record 2 for type1
I hope the question is clear,
Regards.
Join both tables and pivot result:
select *
from (
select id, tainfo1, tainfo2, type, tbinfo1, tbinfo2
from tableA join tableB using (id))
pivot (max(tbinfo1) t1, max(tbinfo2) t2 for type in (1 info1, 2 info2))
Output:
ID TAINFO1 TAINFO2 INFO1_T1 INFO1_T2 INFO2_T1 INFO2_T2
----- ---------- ---------- ---------- ---------- ---------- ----------
1 me 100 good 7 bad 5
2 you 200 so-so 6
3 they 300 awesome 10
SQLFiddle
This will work for defined number of values in column type. Also pivot is available from Oracle 11g version, for older versions use max(decode...) like here. If you need fully dynamical solution then please read articles: link1, link2.

selecting data with highest field value in a field

I have a table, and I'd like to select rows with the highest value. For example:
----------------
| user | index |
----------------
| 1 | 1 |
| 2 | 1 |
| 2 | 2 |
| 3 | 4 |
| 3 | 7 |
| 4 | 1 |
| 5 | 1 |
----------------
Expected result:
----------------
| user | index |
----------------
| 1 | 1 |
| 2 | 2 |
| 3 | 7 |
| 4 | 1 |
| 5 | 1 |
----------------
How may I do so? I assume it can be done by some oracle function I am not aware of?
Thanks in advance :-)
You can use MAX() function for that with grouping user column like this:
SELECT "user"
,MAX("index") AS "index"
FROM Table1
GROUP BY "user"
ORDER BY "user";
Result:
| USER | INDEX |
----------------
| 1 | 1 |
| 2 | 2 |
| 3 | 7 |
| 4 | 1 |
| 5 | 1 |
See this SQLFiddle
if you have more than one column
select user , index
from (
select u.* , row_number() over (partition by user order by index desc) as rnk
from some_table u)
where rnk = 1
user is a reserved word - you should use a different name for the column.
select user,max(index) index from tbl
group by user;
Alternatively, you can use analytic functions:
select user,index, max(index) over (partition by user order by 1 ) highest from YOURTABLE
Note: Try NOT to use words like user, index, date etc.. as your column names, as they are reserved words for Oracle. If you will use, then use them with quotation marks, eg. "index", "date"...