Mysql select statement contains where clause so unsuitable for insert into - mysql

I'm very inexperienced. I've prepared a select statement which gives the information I need to populate a matches table. However it is not suitable because it contains a where clause. Is there a different way to use it, or how can I change it so that it is suitable for INSERT INTO.
The tables are as follows:-
match_order
match_order_id||match_descrip||first_player||second_player
1 1v2 1 2
2 1v3 1 3
3 2v3 2 3
4 1v4 1 4
5 2v4 2 4
6 3v4 3 4
entries
entry_id||round_id||league_id||box_id||box_position
1 1 1 1 1
2 1 1 1 2
3 1 1 1 3
4 1 2 1 4
5 1 2 1 2
6 1 2 1 1
7 1 2 1 1
matches
match_id||round_id||league_id||box_id||match_order_id||player1||player2
I need to insert new rows every month for a new round of matches. League size, box size & positions change each month.
This is the statement which gives the correct rows.
SELECT e.round_id, e.league_id, e.box_id, mo.match_order_id, e.entry_id as player1, e1.entry_id as player2
FROM match_order mo
LEFT JOIN entries e ON mo.first_player = e.box_position
LEFT JOIN entries e1 ON mo.second_player = e1.box_position
WHERE e.round_id = e1.round_id AND e.league_id = e1.league_id AND e.box_id = e1.box_id
ORDER BY round_id, league_id, box_id, match_order_id
Any help & advise would be greatly appreciated.
Thank you

Assuming match_id is an auto-increment column, you have the data for the other columns. You can just add the INSERT statement before your SELECT.
INSERT INTO matches(round_id, leage_id, box_id, match_order_id, player1, player2)
SELECT e.round_id, e.league_id, e.box_id, mo.match_order_id, e.entry_id as player1, e1.entry_id as player2
FROM match_order mo
LEFT JOIN entries e ON mo.first_player = e.box_position
LEFT JOIN entries e1 ON mo.second_player = e1.box_position
WHERE e.round_id = e1.round_id AND e.league_id = e1.league_id AND e.box_id = e1.box_id

Related

SQL QUERY - how to get child records with different types but from the same parent group

I needed a query where to return the finished type records from the service_flow_actions table, but the records must belong to the service_flow table group where there are records that were given play
Table work_order
id
company_id
closed
status
1
1
true
true
2
1
true
true
Table service_flow
id
work_order_id
company_id
1
1
1
2
2
1
3
2
1
Table service_flow_actions
id
work_order_id
service_flow_id
type
company_id
1
1
1
finished
1
2
1
2
play
1
3
2
2
finished
1
4
2
3
play
1
5
2
3
pause
1
6
2
3
finished
1
I had thought of something like that, but it didn't work.
SELECT DISTINCT(service_flow_actions.*)
FROM service_flow_actions
INNER JOIN work_order ON service_flow_actions.work_order_id = work_order.id
LEFT JOIN service_flow_actions t ON work_order.id = t.work_order_id AND t.type = 'play' AND work_order.company_id = 37
WHERE work_order.company_id = 37 AND service_flow_actions.type = 'finished' AND work_order.closed = true AND work_order.status = true
The exists clause helps in such situation, of course you can achieve the same result using the join clause, but I would go for simple solution first, unless I face performance issues.
SELECT *
FROM service_flow_actions
WHERE type = 'finished'
AND EXISTS (
SELECT 1
FROM service_flow_actions sub
WHERE sub.service_flow_id = service_flow_actions.service_flow_id
AND sub.type = 'play'
)

How Sequence Matters in Laravel query builder for mysql

The complied query has different sequence from the code.
The query works but I don't know why it works!
Here is the business:
I get the roomId by the $userId, and then I get all the playerId by the roomId
Steps:
in Table room_player_relations, I get a row where playerId = $userId.
in Table room_player_relations, I get all the rows where roomId = the roomId of the row found in point 1.
select playerId from the rows found in point 2.
Here is the code:
$players = DB::table('room_player_relations as t1')
->where('t1.playerId',$userId)
->join('room_player_relations as t2','t1.roomId','=','t2.roomId')
->select('t2.playerId')
->get();
Here is the query seen in the debugbar:
select `t2`.`playerId` from `room_player_relations` as `t1`
inner join `room_player_relations` as `t2`
on `t1`.`roomId` = `t2`.`roomId`
where `t1`.`playerId` = '1'
It looks stupid because it join 2 the same tables together, the where is put afterward. But it works. Please tell me why? Thanks!
I find out INNER JOIN-ing two table is not sticking two tables together, but matching all the possible ways of the matching key (roomIdin my example). I can actually see the result of INNER JOIN by the following query:
select * from `room_player_relations` as `t1`
inner join `room_player_relations` as `t2`
on `t1`.`roomId` = `t2`.`roomId`
playerId roomId playerId roomId
2 2 2 2
3 2 2 2
1 2 2 2
2 2 3 2
3 2 3 2
1 2 3 2
4 1 4 1
5 1 4 1
4 1 5 1
5 1 5 1
2 2 1 2
3 2 1 2
1 2 1 2

Show Items even if 0 rows with group by

I'm trying to get the query below to show for each item for each store the amount of each of 4 items we have.
It works great, and I created the temporary table to try to increase speed but my problem is that if the table has no rows for a certain product that product does not show up at all.
I'd like to show all four products(prodNo) regardless of if there is actually any of rows for that specific store.
I researched this site and could not find something similar enough for me to figure it out.
CREATE TEMPORARY TABLE IF NOT EXISTS temp_invoice_dates AS
(
SELECT Invoice_detail.del_date,invoice_Detail.StoreNo,mast_stores.SDesc, invoice_Detail.ProdNo,sold_qty,retn_price,retn_qty,sold_price FROM Invoice_detail
LEFT JOIN mast_stores on invoice_detail.StoreNO=mast_stores.Snum
LEFT JOIN invoice on invoice_detail.Del_Date=invoice.Del_Date and invoice_detail.Invoice_No=invoice.Invoice_No
WHERE Cnum IN ('200','210') AND invoice_detail.Del_Date >= "2016-03-01" AND invoice_detail.Del_Date < "2016-04-01"
);
SELECT
temp_invoice_dates.StoreNo,
temp_invoice_dates.SDesc,
DATE_FORMAT(temp_invoice_dates.Del_Date,'%Y') as Year,
DATE_FORMAT(temp_invoice_dates.Del_Date,'%M') as Month,
temp_invoice_dates.ProdNo,
mast_items.IDesc,
SUM(sold_qty) as TotalIn,
SUM(retn_qty) as TotalOut,
ROUND(SUM((sold_qty*sold_price)-(retn_qty*retn_price)),2) as NetSales,
CONCAT(ROUND(SUM(retn_qty)/SUM(sold_qty),2)*100,'%') as StalePerc
FROM mast_Items
LEFT JOIN temp_invoice_dates on temp_invoice_dates.ProdNo=mast_items.Inum
WHERE mast_items.Inum in ('3502','3512','4162','4182')
GROUP BY temp_invoice_dates.StoreNo, ProdNo
ORDER BY temp_invoice_dates.StoreNo, ProdNo;
Drop table temp_invoice_dates;
Results are similar to:
StoreNo Product Count....
1 1 1
1 2 5
1 3 2
1 4 1
2 1 14
2 2 1
2 4 4
3 2 33
3 3 3
Where as I'd like it to be
StoreNo Product Count ....
1 1 1
1 2 5
1 3 2
1 4 1
2 1 14
2 2 1
2 3 0
2 4 4
3 1 0
3 2 33
3 3 3
3 4 0
Something like this should work.
SELECT sp.StoreNo, sp.ProdNo
, ...stuff...
, sp.IDesc, sp.SDesc
, ...more stuff...
FROM (
SELECT i.Inum AS ProdNo, s.Snum AS StoreNo
, i.IDesc, s.SDesc
FROM mast_Items AS i, mast_stores AS s
WHERE i.Inum IN ('3502','3512','4162','4182')
) AS sp
LEFT JOIN temp_invoice_dates AS tid
ON sp.ProdNo = tid.ProdNo
AND sp.StoreNo = tid.StoreNo
GROUP BY sp.StoreNo, sp.ProdNo
ORDER BY sp.StoreNo, sp.ProdNo
;
Normally I recommend against cross joins (as seen in the subquery) but in this case it is exactly what is needed. If the query is slow, you can instead insert the subquery results into a temp table beforehand, index that, and then use the temp table in place of the subquery.
(Edit: should use sp fields when available for grouping and results)

MySQL UPDATE with GROUP and ORDER

I'm trying to make an update on a table so that it can increment the values on 1 column depending on another's order.
Here's how it'd go
ID GROUP_ID ORDER(Desired) ORDER(NOW)
1 1 1 2
2 1 2 3
3 1 3 1
4 2 1 2
5 2 2 1
6 3 1 1
7 3 2 1
8 3 3 2
So what I need is for each ID, to update the ORDER column so it can be consecutive, starting from 1, within each GROUP_ID.
I have found some solutions to similar problems regarding the updates and orders, but none that uses multiple orders for groups within the same table.
Hope I illustrated the problem right. Thanks in advance
You can do it by "ranking" the rows over again. Mysql doesn't support window functions but you can achieve the same results with join and count like this:
UPDATE YourTable t
INNER JOIN(SELECT s.id,s.group_id,count(*) as cnt
FROM YourTable s
INNER JOIN YourTable ss
ON(s.group_id = ss.group_id and s.id >= ss.id)
GROUP BY s.id,s.group_id) tt
ON (t.id = tt.id and t.group_id = tt.group_id)
SET t.order = tt.cnt

How to join two tables with two conditions?

I have two tables:
LLOAN
LOANID SOURCEID LOAN_COMPANY ETC
1 1 3
2 1 3
3 1 1
4 2 1
5 2 1
6 2 1
7 3 1
8 3 1
COMPANY
CompanyID CountryID CompanyIDLLAS
1 1 1
2 1 2
3 1 3
4 2 1
5 3 1
6 4 1
And I want to join them. The SourceID refers to the CountryID and the LOAN_COMPANY refers to the CompanyID. Only country '1' has multiple companies, all the others just have one.
How can I join these two tables correctly? I've tried many different things, of which this came the closest:
SELECT Count(c.CompanyID) FROM dbo.LLOAN As l
LEFT JOIN dbo.Company As c ON c.CountryID = l.SourceID AND c.CompanyID = l.LOAN_COMPANY
But it leaves many rows blank. What is the correct way to join two tables with two conditions?
Try below Query:
SELECT Count(c.CompanyID)
FROM dbo.LLOAN As LL
LEFT JOIN dbo.Company As C
ON (C.CountryID = LL.SourceID)
AND (C.CompanyID = LL.LOAN_COMPANY)
You can group the condition using paranthesis like this:
SELECT Count(c.CompanyID)
FROM dbo.LLOAN As l
LEFT JOIN dbo.Company As c ON (c.CountryID = l.SourceID) AND (c.CompanyID = l.LOAN_COMPANY)