How to combine rows and columns? - sql

I have two tables. I need to combine two table.
This First table.
----------------------------
| row_no | Part No |Qty_A |
----------------------------
| 1 | A | 100 |
| 2 | A | 300 |
----------------------------
Second table.
----------------------------
| row_no | Part No |Qty_B |
----------------------------
| 1 | A | 400 |
| 2 | B | 200 |
----------------------------
This is my result:
--------------------------------------
| row_no | Part No | Qty_A | Qty_B |
--------------------------------------
| 1 | A | 100 | 400 |
| 2 | A | 300 | - |
| 2 | B | - | 200 |
--------------------------------------
Two tables was joined by "row_no" and "Part_no" column.
I try to use "LEFT OUTER JOIN" but results not as expected.
SELECT t1.row_no ,t1.part_no ,t1.Qty_A ,t2.Qty_B
FROM
(SELECT 1 as row_no,'A' as part_no,100 as Qty_A) as t1
LEFT OUTER JOIN
(SELECT 1 as row_no, 'B' as part_no,200 as Qty_B) as t2
ON t1.row_no = t2.row_no and t1.part_no = t2.part_no
Sorry for my unclear example.
Update
This is example from a large transaction.
And I need to group it by Part_no and re-arrange by row number like these.

Try below query with union all:
select row_no ,part_no ,Qty_A , '-' as Qty_B from tableA
union all
select row_no ,part_no ,'-' as Qty_A , Qty_B from tableb
or you can try with full outer join:
SELECT t1.row_no ,t1.part_no ,t1.Qty_A ,t2.Qty_B
FROM
(SELECT 1 as row_no,'A' as part_no,100 as Qty_A) as t1
full OUTER JOIN
(SELECT 1 as row_no, 'B' as part_no,200 as Qty_B) as t2
ON t1.row_no = t2.row_no and t1.part_no = t2.part_no

The UNION operator is used to combine the result-set of two or more SELECT statements.
- Each SELECT statement within UNION must have the same number of
columns
- The columns must also have similar data types
- The columns in each SELECT statement must also be in the same order
The first query in the union statement defines the column names.
So in your case you could
select row_no ,part_no ,Qty_A , null as Qty_B from table1
union all
select row_no ,part_no , null, Qty_B from table2

Related

Grouping data using PostgreSQL based on 2 fields

I have a problem with grouping data in postgresql. let say that I have table called my_table
some_id | description | other_id
---------|-----------------|-----------
1 | description-1 | a
1 | description-2 | b
2 | description-3 | a
2 | description-4 | a
3 | description-5 | a
3 | description-6 | b
3 | description-7 | b
4 | description-8 | a
4 | description-9 | a
4 | description-10 | a
...
I would like to group my database based on some_id then differentiate which one has same and different other_id
I would expecting 2 type of queries: 1 that has same other_id and 1 that has different other_id
Expected result
some_id | description | other_id
---------|-----------------|-----------
2 | description-3 | a
2 | description-4 | a
4 | description-8 | a
4 | description-9 | a
4 | description-10 | a
AND
some_id | description | other_id
---------|-----------------|-----------
1 | description-1 | a
1 | description-2 | b
3 | description-5 | a
3 | description-6 | b
3 | description-7 | b
I am open for suggestion both using sequelize or raw query
thank you
One approach, using MIN and MAX as analytic functions:
WITH cte AS (
SELECT *, MIN(other_id) OVER (PARTITION BY some_id) min_other_id,
MAX(other_id) OVER (PARTITION BY some_id) max_other_id
FROM yourTable
)
-- all some_id the same
SELECT some_id, description, other_id
FROM cte
WHERE min_other_id = max_other_id;
-- not all some_id the same
SELECT some_id, description, other_id
FROM cte
WHERE min_other_id <> max_other_id;
Demo
You can also do this using exists and not exists:
-- all same
select t.*
from my_table t
where not exists (select 1
from my_table t2
where t2.some_id = t.some_id and t2.other_id <> t.other_id
);
-- any different
select t.*
from my_table t
where exists (select 1
from my_table t2
where t2.some_id = t.some_id and t2.other_id <> t.other_id
);
Note that this ignores NULL values. If you want them treated as a "different" value then use is distinct from rather than <>.

Combining multiple tables with same ID

I am trying to combine several tables. The goal is to have them all on one table in the end, but sorted by ID. So if I have a matching ID between some of the tables, it unites into one row based on the ID.
There are more than two tables (I currently have three: table1, table2, table3 but I plan to add more in the future)
Some of the tables don't have the same columns or number of columns.
Some of the tables don't have the same name for the ID column, table1 has "ID" and table2 has it named "identity" and so on...
I try not to include each of all the available columns from every table in the code, because there's a good amount of columns in each of the available tables and I assume adding and naming each one of them in the query would be tiring. I do however know the column name of the ID in each of the tables.
So the column names for the ID are: "ID(table1), Identity(table2), CatalogNum(table3)"
Here's an example,
table1:
**ID** | Name | Price | Date | ....
000212 Rod 200 NULL etc
......
table2:
Descr | **Identitiy** | amount | ...
Silver rod 000212 3 NULL
......
table3:
Type | Price | Condition | **CatalogNum** | .....
Metal NULL 8 000212 etc
Wood 300 1 000313 etc
.....
So end result should look like:
**ID** | Name | Price | Date | Descr | amount | Type | Condition | .... | ... | .....
000212 Rod 200 NULL Silver rod 3 Metal 8 etc NULL etc
000313 NULL 300 NULL NULL NULL Wood 1 NULL NULL etc
is this what you want:
Select b.*, c.*, d.* From
(select ID from table1 union select Identitiy from table2 union select ID from table3)a
left join table1 b on a.ID = b.ID
left join table2 c on a.ID = c.Identitiy
left join table3 d on a.ID = d.ID
Since there's no single source for all of the ID values that could occur in the various tables, you'll have to build one, and then use that to join to all of the other tables to get the columns you're interested in.
For the purposes here, I pulled back all of the columns in all of the tables, though.
WITH IdList AS (
SELECT
ID AS MasterId
FROM table1
UNION
SELECT
Identitiy
FROM table2
UNION
SELECT
CatalogNum
FROM table3
)
SELECT
i.MasterID,
t1.*,
t2.*,
t3.*
FROM IdList as i
LEFT JOIN table1 as t1 ON t1.ID = i.MasterID
LEFT JOIN table2 as t2 ON t2.Identitiy = i.MasterID
LEFT JOIN table3 as t3 ON t3.CatalogNum = i.MasterID;
Result:
+----------+--------+--------+--------+--------+------------+-----------+--------+-------+--------+-----------+------------+
| MasterID | ID | Name | Price | Date | Descr | Identitiy | amount | Type | Price | Condition | CatalogNum |
+----------+--------+--------+--------+--------+------------+-----------+--------+-------+--------+-----------+------------+
| 000212 | 000212 | Rod | 200 | (null) | Silver rod | 000212 | 3 | Metal | (null) | 8 | 000212 |
| 000313 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | Wood | 300 | 1 | 000313 |
+----------+--------+--------+--------+--------+------------+-----------+--------+-------+--------+-----------+------------+
SQL Fiddle demo
EDIT: Your question notes that you want the data in one table, ", but sorted by ID." SQL tables don't work that way. They are, by definition, unordered sets. You impose order on them by using an ORDER BY clause in your SELECT queries. So there is no effort in my query above to create any kind of "order" at all.

SQL get data that doesn't exist on another table

I'm trying to get a query that get me a data that exist in table1 but not on table2, but has the same id with data table2.
In the following example, I'm trying to get 'SecID-by_Bank' 12456 which shares the same ISIN as another 2 items in table2.
I've tried the following query, but it returned me every data that's not on table2, not just the one that shares the same ISIN.
Query:
SELECT tb1_isin, tb1_SecID_by_Bank
FROM table1
WHERE not EXISTS (
SELECT top 1 null
FROM table2
WHERE table1.tb1_ISIN = table2.tb2_isin
)
Table 1
--------------------------------------------
Row | SecID_by_Bank | Desc | ISIN
--------------------------------------------
1 | 421345 | BlaBla | US1354
--------------------------------------------
499 | 34345 | 2.US | XS1545
--------------------------------------------
500 | 45676 | 2/US | XS1545
--------------------------------------------
501 | 12456 | 2-US | XS1545
--------------------------------------------
Table 2
--------------------------------------------
Row | SecID_by_Bank | Desc | ISIN
--------------------------------------------
1 | 34345 | 2.US | XS1545
--------------------------------------------
2 | 45676 | 2/US | XS1545
Query result needed:
SecID_by_Bank | Desc | ISIN
-------------------------------------
| 12456 | 2-US | XS1545
-------------------------------------
What am I missing?
Thank you!
If you build query in Access try:
SELECT Table1.*
FROM Table1
WHERE (((Table1.[ISIN]) In (SELECT ISIN FROM Table2)) AND ((Table1.SecID_by_Bank) Not In (SELECT SecID_by_BANK FROM Table2)));
Or using 1 subquery:
SELECT Table1.*, Table2.ISIN
FROM Table2 RIGHT JOIN Table1 ON Table2.SecID_by_Bank = Table1.SecID_by_Bank
WHERE (((Table1.ISIN) In (SELECT ISIN FROM Table2)) AND ((Table2.ISIN) Is Null));
For query in SQLServer:
select distinct a.SecID_by_Bank, a.[desc], a.isin from #table1 a left join #table2 b
on a.SecID_by_Bank=b.SecID_by_Bank and a.isin=b.isin
join #table2 c on a.isin=c.isin
where b.isin is null

Filter query with a GROUP BY based on column not in GROUP BY statement

Given the following table structure and sample data:
+-------------+------+-------------+
| EmployeeID | Name | WorkWeek |
+--------------+-------+-----------+
| 1 | A | 1 |
| 2 | B | 1 |
| 2 | B | 2 |
| 3 | C | 1 |
| 3 | C | 2 |
| 4 | D | 2 |
+--------------+-------+-----------+
I am looking to select all employees that only worked week 1 (so in this example, only employeeid = 1 would be returned. I am able to get the data with the following query:
SELECT EmployeeId, Name
FROM SomeTable
GROUP BY EmployeeId, Name
HAVING SUM ( WorkWeek ) = 1;
To me, the HAVING SUM( WorkWeek ) = 1 is a hack and this should be handled with some form of a GROUP BY and COUNT but I cannot wrap my head around how that query would be structured.
Any help would be useful and enlightening.
HAVING SUM( WorkWeek ) = 1 may work for week 1 or 2, but will fail for week 3 (since 1+2 = 3).
Use NOT EXISTS operator with a subquery instead:
SELECT EmployeeId, Name
FROM SomeTable t1
WHERE NOT EXISTS (
SELECT * FROM SomeTable t2
WHERE t1.EmployeeId = t2.EmployeeId
AND t2.WorkWeek <> 1
)
Actually, that's exactly why the having clause is for - to filter records according to the aggregated values.
From w3schools sql tutorial:
The HAVING clause was added to SQL because the WHERE keyword could not be used with aggregate functions.

Ordering results by values in other table

I have two tables :
Table1
id | name | age | d_o_b
=====================================
1 | ASD | 22 | 12/01/1992
2 | QWE | 21 | 04/04/1993
3 | FRG | 24 | 04/04/1990
Table2
id | age
===============
1 | 22
2 | 21
3 | 24
Is it possible to order by two columns one from first Table1 and then by one column from Table2.
Something like ..
SELECT * FROM Table1 order by d_o_b , age in (SELECT * FROM Table2)
To order by a column in other table you may need to join them. This should work:
SELECT a.* FROM Table1 a
join table2 b
on a.id=b.id
order by d_o_b,b.age