I have the following query that is doing an INNER JOIN within a select query to insert records into the table. The issue is instead of using the WHERE clause and listing the 3 t2.device I would like to see, I need to do another INNER JOIN with a table called tbl_Full_List.
Both tbl_Full_List and tbl1_device have a column called device so instead of the WHERE clause I would like it to show only devices that match in both tbl_Full_List and tbl1_device
INSERT INTO TEMP_Table1 (place, device, description, quantity)
(SELECT t1.place, t2.device, t2.description, Sum(t2.quantity) AS quantity
FROM Device_Table AS t1
INNER JOIN tbl1_device AS t2
ON t1.rma = t2.rma
WHERE t2.device IN ('PRT1030', 'PRT-23','PRT-20139')
AND t1.date_made = Current_Date()
GROUP BY t1.place, t2.device, t2.description ORDER BY place ASC, device ASC )
Without knowing how the two relate... I'm assuming FL.ID is the PK of full list and we have a Foreign Key to tbl1_devcice called FL_ID
INSERT INTO TEMP_Table1 (place, device, description, quantity)
(SELECT t1.place, t2.device, t2.description, Sum(t2.quantity) AS quantity
FROM Device_Table AS t1
INNER JOIN tbl1_device AS t2
ON t1.rma = t2.rma
INNER JOIN tbl_Full_List FL
ON FL.Device = t2.Device
WHERE t1.date_made = Current_Date()
GROUP BY t1.place, t2.device, t2.description ORDER BY place ASC, device ASC )
Related
I am trying to update a table using data gotten from 3 tables.
table3 contains rates for different days. The rates aren't measured daily so I simply want to use the most recent date with respect to the table2 record which is what prompts the trigger.
So far this is what I have but I can't seem to get it to work.
I'm not sure I'm explaining myself properly to be honest.
CREATE TRIGGER `trigger1`
AFTER UPDATE ON `table2` FOR EACH ROW
UPDATE `table4`
inner join (SELECT o.`Name`,
o.Date,
(o.`value` * (m.`rate`)) total
FROM `table1` o
LEFT JOIN `table2` r
ON o.`Name` = r.`Name`
AND o.Date = r.Date
LEFT JOIN (SELECT * from `table3`
INNER JOIN (SELECT `Name`, Date
WHERE Date < r.Date
ORDER BY Date DESC
LIMIT 1) as y
ON table3.Date = y.Date AND table3.Name = y.Name) m
ON o.`Name` = m.`Name`
GROUP BY o.`Name`, o.Date)x
set `Contribution` = x.total
where (`table4`.Date) = x.Date and `table4`.`Well Name` = x.`Well Name`;
fiddle link : https://www.db-fiddle.com/f/pVqmhmM21XJARKhvFMP52B/4
Is it possible to sum on cols if inner join is true and sum on another cols if another inner join true? i.e.
SELECT t1.debit
, t2.credit
, t1.ID
, t2.ID
FROM
( SELECT SUM(booking_value) debit
, gl_acct.id_fin_gl_acct ID
FROM bookings
JOIN gl_acct
ON (CONCAT('1',gl_acct.id_fin_gl_acct) = bookings.id_debit_account)
) t1
JOIN
( SELECT SUM(booking_value) credit
, gl_acct.id_fin_gl_acct ID
FROM bookings
JOIN gl_acct
ON (CONCAT('1',gl_acct.id_fin_gl_acct)=bookings.id_credit_account)
) t2
ON (t1.ID = t2.ID)
GROUP
BY t1.ID
Please explain your answer.
An example of conditional aggregation.
SELECT t.id_account
, SUM(IF(t.cr_or_db='cr',t.tot_booking_value,0)) AS `tot_credit`
, SUM(IF(t.cr_or_db='db',t.tot_booking_value,0)) AS `tot_debit`
FROM (
SELECT 'cr' AS `cr_or_db`
, c.id_credit_account AS `id_account`
, SUM(c.booking_value) AS `tot_booking_value`
FROM bookings c
GROUP BY c.id_credit_account
UNION ALL
SELECT 'db' AS `cr_or_db`
, d.id_debit_account AS `id_account`
, SUM(d.booking_value) AS `tot_booking_value`
FROM bookings d
GROUP BY d.id_debit_account
) t
GROUP
BY t.id_account
The inline view t gets us total credits for each id_credit_account and total debits for each id_debit_account.
The original query joins both of those id_ columns to the same account table, so we're assuming those are both foreign keys to that other table, which means they are the same datatype...
A join operation would only be required if there is some reason we need to include the gl_acct table. Assuming that id_fin_gl_acct is UNIQUE in gl_acct... we could add the join operation before the GROUP BY clause.
...
) t
JOIN gl_acct g
ON CONCAT('1',g.id_fin_gl_acct) = t.id_account
GROUP
BY t.id_account
I am trying to perform a count across multiple, linked tables:
select
vpp.Name
,count(sx.Occurences) as sx_Occurences
,count(vpp.Occurences) as vpp_Occurences
,count(sd.Occurences) as sd_Occurences
from v_p vpp
left outer join s_x sx on sx.ID = vpp.ID
left outer join s_d sd on sd.ID = vpp.ID
group by vpp.Name
This however gives me incorrect results (doing a count on one table only works fine, but as soon as I add a second (or a third, fourth...) the numbers are wrong.
I believe you are looking for this:
SELECT vpp.Name,
(SELECT count(sx.Occurences) FROM s_x WHERE s_x.ID = vpp.ID) as sx_Occurences,
count(vpp.Occurences) as vpp_Occurences,
(SELECT count(sd.Occurences) FROM s_d WHERE s_d.ID = vpp.ID) as sd_Occurences
FROM v_p vpp
GROUP BY vpp.Name;
You probably have 1:n relationship between at least 2 of the 3 tables. In the resultset you will have more records than you would have if you counted the records by each table individually.
If you want to count the distinct values of the given fields, then use count(distinct ...):
select
vpp.Name
,count(distinct sx.Occurences) as sx_Occurences
,count(distinct vpp.Occurences) as vpp_Occurences
,count(distinct sd.Occurences) as sd_Occurences
from v_p vpp
left outer join s_x sx on sx.ID = vpp.ID
left outer join s_d sd on sd.ID = vpp.ID
group by vpp.Name
Otherwise, you need to do the counting individually by each table. You can combine the 3 queries as subqueries:
select
t1.Name
,sx_Occurences
,vpp_Occurences
,sd_Occurences
from
(select name, id, count(vpp.Occurences) as vpp_Occurences
from v_p vpp
group by name, id) t1
left outer join
(select id, count(sx.Occurences) as sx_Occurences
from s_x sx
group by id) t2 on t1.ID = t2.ID
left outer join
(select id, count(sd.Occurences) as sd_Occurences
from s_d sd
group by id) t3 on t1.ID = t3.ID
Have found similar posts but still stuck - I am trying to apply a sort AFTER I have processed a query and limited the results. My code is
select DISTINCT(t.id) t_id, t.cart_id ,tS.id tS_id, tS.created tS_created, t.value, t.transactionType_id tT_id, tS.member_name, outIn, tT.type type
from(transaction t)
join transactionSummary tS ON tS.id = t.transactionSummary_id
left join transactionType tT ON tT.id = t.transactionType_id
order by t.id DESC
limit 50
I have tried doing a sub select and applying the ORDER BY afterwards but get an error saying Unknown column 't.id' in 'field list'.
The above code (ie without the sub select) works fine but the ORDER BY slows it down so much as the table is huge...
Any suggestions?
Since you're aliasing t.id to t_id, you need to use the alias in the outer query.
SELECT *
FROM (select DISTINCT t.id t_id, t.cart_id ,tS.id tS_id, tS.created tS_created, t.value, t.transactionType_id tT_id, tS.member_name, outIn, tT.type type
from transaction t
join transactionSummary tS ON tS.id = t.transactionSummary_id
left join transactionType tT ON tT.id = t.transactionType_id
limit 50) x
ORDER BY t_id DESC
BTW, the way you wrote DISTINCT(t.id) suggests that you think the distinct operation is only being applied to that one column. DISTINCT applies to the entire SELECT list; if you only want to make certain columns distinct, you must use GROUP BY to specify those columns.
Here's a possible way to rewrite the query that may make it faster:
select DISTINCT t.id t_id, t.cart_id ,tS.id tS_id, tS.created tS_created, t.value, t.transactionType_id tT_id, tS.member_name, outIn, tT.type type
from transaction t
join (select max(id)-500 maxid from transaction) mT on t.id > maxid
join transactionSummary tS ON tS.id = t.transactionSummary_id
left join transactionType tT ON tT.id = t.transactionType_id
order by t_id DESC
limit 50
By filtering down to just the top 500 IDs, the size of the joins and sorting are reduced.
I'm pretty bad at SQL and have been having some troubles doing somewhat of a UNIQUE join of two tables. The SQL structure is somewhat abysmal, but I didn't design it.
I have two tables:
users
uid, ufn, uln, ue
Where users id = uid.
and
transactions
uid, unit, address, start_date
Basically in the transactions table, there are multiple entries per uid. What I am looking to do is select users.ufn, users.uln, users.ue, transactions.unit, transactions.address based on ONLY the newest start_date. Meaning I will only get ONE result per uid. Currently I'm getting returns for ALL uid entries in the transactions table.
I've tried doing some JOINS, LEFT JOINS, and things with MAX, but have been largely unsuccessful.
SELECT * FROM users JOIN ( SELECT unit, address, start_date FROM transactions GROUP BY uid) as a ON users.tenant_id = a.tenant_id
Is what I tried among a mix of other things.
Any hint as to the right direction would be much appreciated. Thank you!
This will get you close. The problem will be if 2 transactions have the same start date for the same user. But if you don't have that case this should work fine.
select u.ufn,
u.uln,
u.ue,
t.unit,
t.address
from users u
inner join (
select uid,
max(start_date) as newest_start_date
from transactions
group by uid) x
on u.uid = x.uid
inner join transactions t
on t.start_Date = x.newest_start_date
and t.uid = u.uid
Your example SQL has "tenant_id" but that is not in your tables example?
Are you running this once or 10000 times a day?
Try this:
SELECT users.ufn, users.uln, users.ue, transactions.unit, transactions.address
FROM users join transactions on users.uid = transactions.uid
WHERE transactions.UID, transactions.start_date IN
(SELECT UID, MAX(start_date) FROM TRANSACTIONS GROUP BY UID);
Another option is to use an ANTI JOIN on an inequality
select users.ufn,
users.uln,
users.ue,
t.unit,
t.address
from users
INNER JOIN transactions t
ON t.uid = u.uid
LEFT JOIN transactions t1
ON t.uid = t1.uid
and t.start_date < t1.start_date
WHERE
t1.uid is null
Because of t.start_date < t1.start_date and t1.uid is null only records that don't have another record with a greater start_date will be selected
As with MAX() if two or more transaction have start_dates that tie for a user you will get both
This query could work:
SELECT
u.ufn,
u.uln,
u.ue,
t2.unit,
t2.address
FROM
users AS u
INNER JOIN
(
SELECT
uid
, MAX(start_date) AS start_date
FROM
transactions
WHERE
uid = users.uid
) AS t1
INNER JOIN
transaction AS t2 ON t2.uid = t1.uid AND t2.start_date = t1.start_date
Temporary tables are also an option (may be faster, you have to try):
CREATE TEMPORARY TABLE
last_transactions
AS SELECT
uid
, MAX(start_date) AS start_date
FROM
transactions
GROUP BY
uid
;
SELECT
u.ufn,
u.uln,
u.ue,
t2.unit,
t2.address
FROM
users AS u
INNER JOIN
last_transactions AS t1 ON t1.uid = u.uid
INNER JOIN
transaction AS t2 ON t2.uid = t1.uid AND t2.start_date = t1.start_date
P.S.: You should definitely consider adding a primary key to the transactions table. This would allow for a better join clause between t1 and t2. Also, it would prevent duplicates that may occur when multiple start_date occur for the same user.
P.P.S.: wouldn't adding a last_transaction_start_date column to the user table be wiser?
I am not sure if this would be exactly same syntax in MySQL (most likely it will be), but here is how you would do it in SQL server.
Use a rank() function to determine the latest date.
SELECT x.* , y.*
FROM users as x
JOIN
(SELECT *, RANK() Over (Partition By UID Order By Start_Date DESC) as Rank_ FROM Transactions) as y
ON x.uid = y.uid and y.rank_ = 1
Hope this helps.
Cheers!