Joining tables in oracle - sql

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.

Related

SQL QUERY Append Two Columns [duplicate]

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 |

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 match variable data in SQL Server

I need to map a many-to-many relationship between two flat tables. Table A contains a list of possible configurations (where each column is a question and the cell value is the answer). NULL values denote that the answer does not matter. Table B contains actual configurations with the same columns.
Ultimately, I need the final results to show which configurations are mapped between table B and A:
Example
ActualId | ConfigId
---------+---------
5 | 1
6 | 1
8 | 2
. | .
. | .
. | .
N | M
To give a simple example of the tables and data I'm working with, the first table would look like such:
Table A
--------
ConfigId | Size | Color | Cylinders | ... | ColumnN
---------+------+-------+-----------+-----+--------
1 | 3 | | 4 | ... | 5
2 | 4 | 5 | 5 | ... | 5
3 | | 5 | | ... | 5
And Table B would look like this:
Table B
-------
ActualId | Size | Color | Cylinders | ... | ColumnN
---------+------+-------+-----------+-----+--------
1 | 3 | 1 | 4 | ... | 5
2 | 3 | 8 | 4 | ... | 5
3 | 4 | 5 | 5 | ... | 5
4 | 7 | 5 | 6 | ... | 5
Since the NULL values denote that any value can work, the expected result would be:
Expected
---------
ActualId | ConfigId
---------+---------
1 | 1
2 | 1
3 | 2
3 | 3
4 | 3
I'm trying to figure out the best way to go about matching the actual data which has over a hundred columns. I know trying to check each and every column for NULL values is absolutely wrong and will not perform well. I'm really fascinated with this problem and would love some help to find the best way to tackle this.
So, this joins table a on size, color and cylinders.
The size match will be A against B:
If A.SIZE is null, the compare will B.SIZE=B.SIZE which will always return true.
If A.SIZE is not null, the compare will be A.SIZE=B.SIZE which will only be true if they match.
The matching on color and cylinders are similar.
SELECT * FROM TABLEA A
INNER JOIN TABLEB B ON ISNULL(A.SIZE, B.SIZE)=B.SIZE
AND ISNULL(A.COLOR, B.COLOR)=B.COLOR
AND ISNULL(A.CYLINDERS, B.CYLINDERS)=B.CYLINDERS

a column that increments for every row where column A = number and resets to zero when A = another number and increments again

I need a column (LineCount) that increments for every instance of an ID in another column (ItemID) for example:
|ItemID|LineCount|
------------------
| 1 | 1
------------------
| 1 | 2
------------------
| 1 | 3
------------------
| 2 | 1
------------------
| 2 | 2
------------------
| 2 | 3
------------------
| 2 | 4
------------------
| 2 | 5
------------------
| 3 | 1
------------------
| 3 | 2
------------------
| 3 | 3
------------------
| 3 | 4
SQL may look something like:
"Insert into TableA increment LineCount Where ITEMID = #ITEMID"
Your code looks like SQL Server's. If so, you can use window function row_number to generate partitioned sequence numbers.
insert into tablea
select itemId,
row_number() over (
partition by itemId order by itemId
)
from your_table;

SQL Group by one column and decide which column to choose

Let's say I have data like this :
| id | code | name | number |
-----------------------------------------------
| 1 | 20 | A | 10 |
| 2 | 20 | B | 20 |
| 3 | 10 | C | 30 |
| 4 | 10 | D | 80 |
I would like to group rows by code value, but get real rows back (not some aggregate function).
I know that just
select *
from table
group by code
won't work because database don't know which row to return where code is the same.
So my question is how to tell database to select (for example) the lower number column so in my case
| id | code | name | number |
-----------------------------------------------
| 1 | 20 | A | 10 |
| 3 | 10 | C | 30 |
P.S.
I know how to do this by PARTITION but this is only allowed in Oracle databases and can't be created in JPA criteria builder (what is my ultimate goal).
Why You don't use code like this?
SELECT
id,
code,
name,
number
FROM
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY code ORDER BY number ASC) AS RowNo
FROM table
) s
WHERE s.RowNo = 1
You can look at this site;
Data Partitioning