Query for update stock quantity in transaction [closed] - php

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm having trouble with my query because I have to deduct the quantity of the product from a different stock_code.
Let say the customer will buy a product in item_code (I0015) for 20 quantities. First I want to deduct the 12 quantities to the stock_code (ST0016) and the stock will become 0, and the remaining 8 quantities will deduct in stock_code (ST0012), the deduction of quantity is based on the ascending date of stock_expired.
How do I query that in MySQL? Thank you so much! The answer is highly appreciated. The name of my table is stocks_table

Is code below the solution (fiddle)?
with cte as(
select * from(
select *, case when cumulsum <= TotalRequiredQuantity then 0 else cumulsum-TotalRequiredQuantity end NewQuantity
from(
select *, 20 TotalRequiredQuantity,/*Set valid quantitity*/
sum(stock_quantity) over(partition by item_code order by stock_expired) cumulsum
from stocks_table
where item_code = 'I0015'/*Set valid item_code*/
)q
)q1
where stock_quantity>=NewQuantity)
update stocks_table st
join cte on st.id=cte.id
set st.stock_quantity = NewQuantity
without common table expression:
update stocks_table st
join(
select * from(
select *
,case when cumulsum <= TotalRequiredQuantity then 0 else cumulsum-TotalRequiredQuantity end NewQuantity
from(
select *, 20 TotalRequiredQuantity,/*Set valid quantitity*/
sum(stock_quantity) over(partition by item_code order by stock_expired) cumulsum
from stocks_table
where item_code = 'I0015'/*Set valid item_code*/
)q
)q1
where stock_quantity>=NewQuantity
)cte on st.id=cte.id
set st.stock_quantity = NewQuantity

Related

How to left join then get the latest row in second table using where date [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Is anyone know how to query this example table?
Images on imgur
I think it is a left join from the table branches to the table branch_operationals which I need to put where date inside the query.
Here are the examples:
TABLE branches
id
code
name
1
T2QD5
NewYork_Spot
2
MKGHB
London_Spot
3
IGHCZ
Miami_Spot
4
PJDSO
Tokyo_Spot
TABLE branch_operationals
id
branch_id
date
status
1
2
2020-12-05
closed
2
2
2020-12-06
closed
3
3
2020-12-06
open
4
2
2020-12-06
closed
5
2
2020-12-06
open
6
1
2020-12-16
closed
EXPECTED RESULT
id (from 'branches.id')
code
name
date
status
1
T2QD5
NewYork_Spot
2020-12-09
closed
2
MKGHB
London_Spot
2020-12-09
open
3
IGHCZ
Miami_Spot
2020-12-09
open
4
PJDSO
Tokyo_Spot
2020-12-09
null
And here is my current query:
select * from `branches` left join `branch_operationals` on `branches`.`id` = `branch_operationals`.`branch_id` where (`date` = 2020-12-21)
However, it returns null (empty data). But when I remove the where statement, it shows all data from the table branch_operationals with each data from table branches.
Currently I am using Laravel 8, and here is my Laravel syntax:
$branches = Branch::leftJoin('branch_operationals','branches.id','branch_operationals.branch_id')->where(function($q) use($request){
if($request->search){
$q->where(function($q) use($request){
$q->where('code','like','%'.$request->search.'%');
$q->orWhere('name','like','%'.$request->search.'%');
});
}
if($request->date_filter){
$q->where('date',$request->date_filter);
}else{
$q->where('date',\Carbon\Carbon::now()->toDateString());
}
})->get();
I need the query syntax or the Laravel Eloquent syntax.
I can provide you the query syntax which is normal LEFT JOIN.
The issue with your query is that you are doing INNER JOIN by applying the condition on the Left joined table in the WHERE clause. You can achieve the desired result as follows:
select * from
(select b.*, bo.*, -- use the needed column names with proper alias here. I have used *
row_number() over (partition by b.id order by bo.date desc) as rn
from branches b
left join branch_operationals bo on b.id = bo.branch_id and date <= 2020-12-21) t
where rn = 1
maybe it will work for you
select b.id ,b.code,b.name ,'2020-12-06' date ,o.status from branch b
left join ( select bo.id, bo.branch_id, bo.date, bo.status from
(select branch_id , max(id) id from branch_operationals where date='2020-12-06' group by branch_id ) as tmp
join branch_operationals bo on bo.id=tmp.id ) as o on b.id=o.branch_id

how to sort mysql data and find position? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have mysql data of 3 rows (user_id, exam_id, marks).
I want to find each user ranking position based on marks and exam_id .
How will be the SQL query with php code for this. Please help me. Thanks in advance.
Here is partial code
$p = "SELECT * FROM IDTABLE WHERE EID = '$info[EID]'";
$rowp = mysqli_query($conn, $p);
while (($ret = mysqli_fetch_assoc($rowp)) > 0) {
$q = "SELECT * FROM INFOTABLE WHERE EID = '$ret[EID]'";
$rowq = mysqli_query($conn, $q);
while (($retq = mysqli_fetch_assoc($rowq)) > 0) {
$user[$ret['EID'] . $retq['UID']] = $retq['Marks'];
}
}
arsort($user);
var_dump($user);
First of all you should consider a few things:
You should always better search for an already answered question before posting a new one (it's part of stack overflow's code)
Bring more information of what you want, being as clear as possible
Giving more details (for example: you sql structure)
However, I will try to give you a hint - Hope it helps!
For example you want to order your user_id based on their marks:
select user_id from my_table order by "marks" asc;
For example you want to order your user_id based on their marks and exam_id :
select user_id from my_table order by "marks", "exam_id" asc;
For example you want to create a kind of ranking based on users's marks:
SET #rank := 0;
SELECT
*,
#rank := #rank + 1 AS rank
FROM my_table
order by marks ASC;
For example you want to get the ranking number from a specific
SET #rank := 0;
SELECT * from ( select
*,
#rank := #rank + 1
FROM my_table
order by marks ASC ) AS rank where user_id = 2;
Hope this helps! You could get more information about mysql's ranking here
Regards,

Ordering by different column depending on value of another column

There are two type of questions there 1.Passage and 2.Normal questions.
usally in test i want to pick random questions which consist type_id=0 in that if type=1 question come the the next passage should be relates to that question(Comprehension question should come in sequential). By using the below query i am able to get the questions
SELECT *
FROM tbl_testquestion
ORDER BY
CASE
WHEN type_id=0 THEN RAND()
WHEN type_id=1 THEN qu_id
END ASC
all the passage questions are coming last
and i have limit of 40 questions for test and in the table i have 50 passage questions and 70 Normal questions.
How can i write a query to call passage questions in between normal
questions.
EXAMPLE
1.who is the president of America.?(type_id=0)
2.A,B,C are 3 students Aname is "Arun" B name is "Mike" C name is "Jhon"(type_id=1)
who is C from the above passage
3.A,B,C are 3 students Aname is "Arun" B name is "Mike" C name is "Jhon"(type_id=1)
who is A from the above passage
4.Who is CEO of Facebook.?(type_id=0)
Form the Above 4 question we will pick random if Question 1 comes in that rand() no problem when the question 2 comes in the rand() the next question should be sequential. it means next question should be 3 after that passage questions completed it should switch back to rand() functionality
I think that the design of your database should be improved, but I’m going to answer your question as it stands.
I think I have a rather simple solution, which I can express in portable SQL without CTE’s.
It works this way: let’s assign two numbers to each row, call them major (an integer, just to be safe let’s make it a multiple of ten) and minor (a float between 0 and 1). For type 0 questions, minor is always 0. Each type 1 question relating to the same passage gets the same major (we do this with a join with a grouped subselect). We then order the table by the sum of the two values.
It will be slow, because it joins using a text field. It would be better if each distinct passage_description had an integer id to be used for the join.
I assume that all type 0 questions have empty or null passage_description, while type 1 questions have them non-empty (it would make no sense otherwise.)
I assume you have a RAND() function which yields floating values between 0 and 1.
Here we go:
SELECT u.qu_id, u.type_id,
u.passage_description, u.passage_image,
u.cat_id, u.subcat_id,
u.question, u.q_instruction, u.qu_status
FROM (
SELECT grouped.major, RAND()+0.001 AS minor, t1.*
FROM tbl_testquestion t1
JOIN (SELECT 10*FLOOR(1000*RAND()) major, passage_description
FROM tbl_testquestion WHERE type_id = 1
GROUP BY passage_description) grouped
USING (passage_description)
-- LIMIT 39
UNION
SELECT 10*FLOOR(1000*RAND()) major, 0 minor, t0.*
FROM tbl_testquestion t0 WHERE type_id = 0
) u ORDER BY u.major+u.minor ASC LIMIT 40;
With the above query without modifications, there is still a small probability that you get questions of only one type. If you want to be sure that you have at least one type 0 question, you can uncomment the LIMIT 39 on the first part of the UNION. If you want at least two, then say LIMIT 38, and so on. All type 1 questions related to the same passage will be grouped together in one test; it is not guaranteed that all questions in the database related to that passage will be in the test, but in a comment above you mention that this can be “broke”.
Edited:
I added a small amount to minor, just to bypass the rare but possible case in which RAND() returns exactly zero. Since major goes by tens, the fact that minor might now be greater than one is immaterial.
Use the following, I haven't tested this so, if there are any errors please report back, I will correct them. $r is a random value produced by PHP for this query. You could do $r = rand(); before calling the query
SELECT * FROM (
UNION((
SELECT *, RAND()*(SELECT COUNT(*) FROM tbl_testquestions) as orderid
FROM tbl_testquestion
WHERE type_id=0
ORDER BY orderid
LIMIT 20
),(
SELECT *, MD5(CONCAT('$r', passage_description)) as orderid
FROM tbl_testquestion
WHERE type_id=1
ORDER BY orderid
LIMIT 20
))
) AS t1
ORDER BY orderid
Explanation: orderid will keep type_id=1 entries together as it would produce the same random sequence for the same passage questions.
Warning: Unless you add passage_id to the table, this question will work quite slowly.
Edit: Fixed the ordering (I hope), forgot that MYSQL generates random numbers between 0 and 1.
This is the solution for mysql,
sorry it is not so readable because mysql does not supports CTE like sql-server.
Maybe you can compare with sql-server CTE syntax to the bottom to better understand how it works.
select
d.*
, o.q_ix, rnd_ord -- this is only for your reference
from (
select *, floor(rand()*1000) as rnd_ord -- this is main order for questions and groups
from (
select * from (
select
(#r1 := #r1 - 1) as q_ix, -- this is row_number() (negative so we can keep group separated)
passage_description, 0 qu_id, type_id
from (
select distinct passage_description, type_id
from tbl_testquestion,
(SELECT #r1 := 0) v, -- this is the trick for row_number()
(SELECT #rnd_limit := -floor(rand()*3)) r -- this is the trick for dynamic random limit
where type_id=1
) p
order by passage_description -- order by for row_number()
) op
where q_ix < #rnd_limit
union all
select * from (
select
(#r2 := #r2 + 1) as q_ix, -- again row_number()
'' as passage_description, qu_id, type_id
from tbl_testquestion,
(SELECT #r2 := 0) v -- var for row_number
where type_id=0
order by qu_id -- order by for row_number()
) oq
) q
) o
-- look at double join for questions and groups
join tbl_testquestion d on
((d.passage_description = o.passage_description) and (d.type_id=1))
or
((d.qu_id=o.qu_id) and (d.type_id=0))
order by rnd_ord
limit 40
and this is the more readable sql-server syntax:
;with
p as (
-- select a random number of groups (0-2) and label groups (-1,-2)
select top (abs(checksum(NEWID())) % 3) -ROW_NUMBER() over (order by passage_description) p_id, passage_description
from (
select distinct passage_description
from d
where type_id=1
) x
),
q as (
-- label questions (1..n)
select ROW_NUMBER() over (order by qu_id) q_ix, qu_id
from d
where type_id=0
),
o as (
-- calculate final order
select *, ROW_NUMBER() over (order by newid()) rnd_ord
from (
select p.q_ix, passage_description, 0 qu_id from p
union all
select q.q_ix, '', qu_id from q
) x
)
select top 40
d.*
, o.rnd_ord, o.q_ix
from o
join d on
((d.passage_description = o.passage_description) and (d.type_id=1))
or
((d.qu_id = o.qu_id) and (d.type_id=0))
order by
rnd_ord
that's all

Updating row from select results [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am on a project of which requires Ranking and outputing the total score to users.
I have a table called userdata like this
id matricno mtstotal engtotal grandtotal Rank
1 MXX001 6 4
2 MXX002 9 8
3 MXX003 5 3
4 MXX004 4 7
5 MXX005 7 2
SELECT * FROM (
SELECT s.*, #rank := #rank + 1 rank FROM (
SELECT matricno, sum(mtstotal + engtotal) TotalPoints FROM userdata
WHERE class='1' AND subclass='A'
GROUP BY matricno
) s, (SELECT #rank := 0) init
ORDER BY TotalPoints DESC
) r
This SQL creates something temporary
matricno TotalPoints rank
MXX002 17 1
MXX004 11 2
MXX001 10 3
MXX005 9 4
MXX003 8 5
What I want is a statement added to the one above that will copy the TotalPoints and rank values and update the grandtotal and Rank columns respectively.
Even if it is formatting another code but it should be able to sum, rank and update in one single coding
When updating userdata join it with your query as subselect and use values from it
UPDATE userdata ud
JOIN(
SELECT s.*, #rank := #rank + 1 rank FROM (
SELECT matricno, sum(mtstotal + engtotal) TotalPoints FROM userdata
WHERE class='1' AND subclass='A'
GROUP BY matricno
) s, (SELECT #rank := 0) init
ORDER BY TotalPoints DESC
) r ON r.matricno = ud.matricno
SET ud.grandtotal = r.TotalPoints,
ud.Rank = r.rank

mysql - one more complex query or two simple [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I would like to know which query is better. I want to select some specific records and all count of records in table(but filtered).
Which query is better?
SELECT name, surname,
(select COUNT(messages.id) from messages WHERE `messages`.`archived` = '0' AND `type` IN (0, 1) ) as count
FROM messages JOIN
users
ON users.id = messages.user_id
WHERE messages.archived = 0 AND type = 0 OR type = 1
ORDER BY created_on DESC
LIMIT 3
or
SELECT name, surname
FROM messages JOIN
users
ON users.id = messages.user_id
WHERE messages.archived = 0 AND type = 0 OR type = 1
ORDER BY created_on DESC
LIMIT 3
with
SELECT count(id) as count
FROM messages
WHERE `messages`.`archived` = '0' AND `type` IN (0, 1)
If I have big db I will check this out, but for now I have got a few records.
With single query the count is added to every record.
Thanks and sorry for my english!
After writing this, I realized that the two queries are not the same. So, you should use the version that corresponds the results you want to get. (Do you want the count filtered or not?)
I'm not sure if MySQL will optimize the subquery in the SELECT. However, you can just move it into the FROM clause, where it is only run once:
SELECT `name`, `surname`, m.cnt
FROM `messages` JOIN
`users`
ON `users`.`id` = `messages`.`user_id` CROSS JOIN
(select COUNT(messages.id) as cnt from messages) m
WHERE `messages`.`archived` = '0' AND `type` = 0 OR `type` = 1
ORDER BY `created_on` DESC;
LIMIT 3
I suspect your WHERE clause is incorrect. Do you really intend this?
WHERE `messages`.`archived` = '0' AND `type` IN (0, 1)

Categories