Combining date based on four different tables in SQL environment - mysql

Master_table Table_A
ID Problem Date ID Problem Date
101 123 01-02-1993 101 123 01-02-1993
101 124 101 124
102 125 102 125 07-02-1994
103 126 08-22-1999 103 126 08-22-1999
103 131 103 131 08-09-1999
Table_B Table_C
ID Problem Date ID Problem Date
101 124 101 124
102 125 06-30-1994 102 125
103 126 08-22-1999 103 131 08-08-1999
103 131 08-09-1999 106 137 02-02-1987
106 137 01-02-1987 110 145 12-22-1995
I need to create a new table named ‘final_table’ such that all observations in Master_table have a date. Rule for achieving this: Date from Master_table will be used as the date when Date exists. Otherwise, the minimum Date from Table_A, Table_B and Table_C will be used. If Date is missing in all the tables then drop the observation.
Desired Output
ID Problem Date
101 123 01-02-1993
102 125 06-30-1994
103 126 08-22-1999
103 131 08-08-1999
What I've tried
SELECT ID, Problem, MIN(Date) as Date
FROM
( SELECT ID, Problem, Date
FROM Table_A
UNION ALL
SELECT ID, Problem, Date
FROM Table_B
UNION ALL
SELECT ID, Problem, Date
FROM Table_C
) as subQuery
Delete From table Where Date IS NULL

Seeme you need a union between the 3 tables this way
select id, problem, data
from Table_A
where date is not null
union
select id, problem, min(data)
from Table_B
group by id, problem
where date is not null
union
select id, problem, min(data)
from Table_B
group by id, problem
where date is not null

Related

Join tables showing unique values in each row

I have 2 tables called cash and check
CASH
cstm_id
cash_date
cash_amount
101
20220529
50
101
20220530
100
102
20220601
50
102
20220603
75
CHECK
cstm_id
check_date
check_amount
101
20210525
150
101
20210812
25
102
20220210
25
102
20220603
20
I want to join the tables so I have unique values in each row without any duplication
EXPECTED RESULT:
cstm_id
cash_date
cash_amount
check_date
check_amount
101
20220529
50
null
null
101
20220530
100
null
null
101
null
null
20210525
150
101
null
null
20210812
25
102
20220601
50
null
null
102
null
null
20210110
25
102
20220603
75
20220603
20
What would be the most appropriate sql script for this output
One approach can be via full outer join -
select distinct * from (
select c.*, c1.check_date, c1.check_amount
from cash c left join check1 c1
on c.cstm_id=c1.cstm_id
and c.cash_date = c1.check_date
union all
select c1.cstm_id,c.cash_date,c.cash_amount, c1.check_date, c1.check_amount
from cash c right join check1 c1
on c.cstm_id=c1.cstm_id
and c.cash_date = c1.check_date
) t;
Fiddle.

Get max score and store in another column

This is my table:
student_id
subject_id
total
max
101
1
90
102
2
80
103
1
95
101
1
82
103
2
76
104
1
95
101
2
71
I want to get the max total in a particular subject and store it in another column whenever the total column is inserted or updated.
This is what I want the table to look like:
student_id
subject_id
total
max
101
1
90
95
102
2
80
80
103
1
95
95
101
1
82
95
103
2
76
80
104
1
95
95
101
2
71
80
I have tried this query but it doesn't add the max scores in each subject against all the student_id.
SELECT MAX(`total`) AS highest
FROM results
GROUP BY student_id
I suppose I should use a trigger for this but the normal query is also okay by me.
If your column does not yet exist in your table, you need to add it with an ALTER statement.
ALTER TABLE <your_table_name> ADD max INT;
Then you can first select the "max" value for each "subject_id" using an aggregation, then use it inside the UPDATE statement exploiting a JOIN operation:
UPDATE <your_table_name>
INNER JOIN (SELECT subject_id,
MAX(total) AS total_max
FROM <your_table_name>
GROUP BY subject_id) cte
ON <your_table_name>.subject_id = cte.subject_id
SET <your_table_name>.max = cte.total_max;
Check the demo here.
Assuming you are using MySQL 8+.
Ideally, instead of storing MaxTotal data into each column, you should get such the data while selecting like this:
WITH CTE AS (SELECT subject_id,MAX(total) AS MaxTotal
FROM results
GROUP BY subject_id
)
SELECT results.*,CTE.MaxTotal
FROM results
JOIN CTE ON results.subject_id = CTE.subject_id;
However, if you still need to update it anyway, use UPDATE with JOIN
WITH CTE AS (SELECT subject_id,MAX(total) AS MaxTotal
FROM results
GROUP BY subject_id
)
UPDATE results
JOIN CTE ON results.subject_id = CTE.subject_id
SET results.MaxTotal = CTE.MaxTotal;
Output after the update:
student_id
subject_id
total
MaxTotal
101
1
90
95
102
2
80
80
103
1
95
95
101
1
82
95
103
2
76
80
104
1
95
95
101
2
71
80
See this db<>fiddle.

How to find all items in a column that fit a criteria within another column in SQL

I need to find in the table scores, the student numbers that has all the grades in between 70 and 90. The answer should only return 105 and 108 since they are the only student numbers that fit the criteria. I keep getting 105,108, and 109 for some reason but I can't see why. This is the table below.
SCORES
sno | grade
101 | 64
109 | 68
105 | 75
109 | 76
108 | 78
107 | 79
108 | 81
101 | 85
NULL | 86
105 | 88
107 | 91
103 | 92
This is the query that is giving me that result.
SELECT sno
FROM scores
GROUP BY sno
HAVING grade BETWEEN 70 and 90;```
I think you're after something like this:
SELECT sno, MIN(grade) as mingrade, MAX(grade) AS maxgrade
FROM scores
GROUP BY sno
HAVING MIN(grade) >= 70 AND MAX(grade) <= 90
but note that this will return the row that has a null value for "sno" because this row fits your criteria. You can always add WHERE sno IS NOT NULL after the FROM scores if you want to exclude that row.
NOTE: Obviously you can leave out the mingrade/maxgrade columns if you don't wish to have them in the result set.
ADDITIONAL NOTE: I presume you are using SQLite? Most other SQL dialects complain about the syntax in your example because they expect an aggregate function to apply on the columns used in the HAVING clause.
For what it's worth, there's an online demo here
What about this:
WITH OUTSIDE_GRADES
AS
(
SELECT SNO FROM SCORES
WHERE 1=1
AND (GRADE < 70 OR GRADE > 90)
)
SELECT distinct SNO FROM SCORES WHERE SNO NOT IN (SELECT SNO FROM
OUTSIDE_GRADES)

sql check if rows are subset of another table

will you help my problem? I have a tblProduct which is a bill of material for producing items with decal. tblStock is the available decal that is in stock. I need a query to check which product can be manufactured based on the available decal. The product can only be produced if all the decals are available. Thanks so much in advanced
tblProduct
Id decal_1 decal_2 decal_3
1 111 121 144
2 104 106 144
3 121 144 163
4 122 144 163
5 (null) 163 191
6 104 121 163
tblStock
Available_decal
111
121
144
163
191
Desired Output
Id
1
3
5
Note that there is a null in number 5. this complicates the matter
An IN check should do it
SELECT
*
FROM
tblProduct
WHERE
(decal_1 IS NULL OR decal_1 IN (SELECT Available_decal FROM tblStock))
AND (decal_2 IS NULL OR decal_2 IN (SELECT Available_decal FROM tblStock))
AND (decal_3 IS NULL OR decal_3 IN (SELECT Available_decal FROM tblStock))
Another way with EXISTS:
SELECT
*
FROM
tblProduct
WHERE
(decal_1 IS NULL OR EXISTS (SELECT 1 FROM tblStock WHERE Available_decal = decal_1))
AND (decal_2 IS NULL OR EXISTS (SELECT 1 FROM tblStock WHERE Available_decal = decal_2))
AND (decal_3 IS NULL OR EXISTS (SELECT 1 FROM tblStock WHERE Available_decal = decal_3))

MySQL Group By not producing expected result

This is my table structure:
rec_id product_id quantity quantity_in quantity_out balance stock_date status
1 2 342 NULL 17 325 2009-10-23 1
2 2 325 NULL 124 201 2009-10-23 1
3 1 156 NULL 45 111 2009-10-23 1
4 2 201 NULL 200 1 2009-10-23 1
5 2 1 NULL 1 0 2009-10-23 1
6 1 111 NULL 35 76 2009-10-23 1
All I want is the last transaction done for a given product: product_id, quantity, quantity_out and balance from this table.
Example, there are 2 transaction done for product 2 (ids 1 & 2):
final balance for product_id 2 is 0 -> stored in rec_id 5
final balance for product_id 1 is 76 -> stored in rec_id 6
Final result/output should be like this:
recid productid quantity quantityin quantityout balance stock_date status
5 2 1 NULL 1 0 2009-10-23 1
6 1 111 NULL 35 76 2009-10-23 1
You can find the latest record for each product like:
select max(rec_id) as MaxRec
from YourTable
group by product_id
Using a subquery, you can retrieve the latest rows for their product:
select *
from YourTable
where rec_id in (
select max(rec_id) as MaxRec
from YourTable
group by product_id
)
Here's a single query with no subqueries:
SELECT main.*
FROM YourTable main
LEFT JOIN YourTable newer
ON newer.product_id = main.product_id AND newer.rec_id > main.rec_id
WHERE newer.rec_id IS NULL;
You can tweak the field list however you want--make sure you select fields from main, not newer, which should be all null.