Multiple new variable in mysql query - mysql

My problem is simple, I'm using the query
(ReturnItm.PackQty * ReturnItm.ReturnQty) as Total_Qty,
CASE
WHEN ReturnItm.UOM='U' THEN
IF(Inventory.Price=0,Inventory.Pricec,Inventory.Price)
WHEN ReturnItm.UOM='P' THEN Inventory.Pricep
ELSE Inventory.Pricec
END AS Price
So, how to multiple that Total_Qty and Price?
Is it just like this?
(Total_Qty*Price) as Total_price
Help me, please

To select this product in the same select clause, you'll have to repeat the full expressions:
SELECT
Test.1,
Test.2,
Test.3,
Test.4,
(Test.1 * Test.2) AS TestNew1,
(Test.3 * Test.4) AS TestNew2,
Test.1 * Test.2 * Test.3 * Test.4 AS TotalTest
FROM Test;

Use a sub-query...
SELECT
*,
(TestNew1 * TestNew2) as TotalTest
FROM
(
SELECT
Test.1,
Test.2,
Test.3,
Test.4,
(Test.1 * Test.2) as TestNew1,
(Test.3 * Test.4) as TestNew2
FROM
Test
)
AS x
The inner query acts as a scope within which the new columns can be expressed, and the outer query acts as a scope where there can be referrenced.
Also, in terms of performance, note that SQL isn't executed as written. It's a "declarative" language; it's a means of expressing the functionality, and then the DBMS turns than in to an actual execution plan.

Related

Expressing two combined conditions in mysql

I have this table with some data that i am interested in. The table is called trades. basically, i want to select all data in that table but this conditions must hold.
trade_session_status="DONE"
(trade_prediction="up" AND trade_result="up" ) OR (trade_prediction="down" AND trade_result="down" )
I have written the whole query like this
select * from trades where trade_session_status="DONE" AND
(trade_prediction="up" AND trade_result="up" ) OR
(trade_prediction="down" AND trade_result="down" )
I want to get all data where trade_session_status is "DONE" and someone predicted up and the result indeed came to be up or someone who predicted down and the result came to be down.
The query returns some data without any error. Is my query expression correct?.
You need to add additional brackets:
select *
from trades
where trade_session_status="DONE"
AND ((trade_prediction="up" AND trade_result="up" )
OR (trade_prediction="down" AND trade_result="down" ))
Alternatively:
select *
from trades
where trade_session_status='DONE'
AND (trade_prediction, trade_result) IN (('up', 'up'),('down', 'down'))

Multiple AND/OR logic messed up

I need to get my data when userID=4 and status= In use or Pending or Deleted.
But I am getting extra data not sure why.
I am getting extra data from
userid=3
MySQL query is:
SELECT * FROM `registered_bicycle`
WHERE (`userID`='4')
AND (`status`='In Use')
OR (`status`='Pending')
OR (`status`='Deleted')
You have to use (...) arround the OR Statements:
SELECT * FROM `registered_bicycle`
WHERE (`userID`='4')
AND (`status`='In Use'
OR `status`='Pending'
OR `status`='Deleted')
or use IN function
Put the part after the AND between braces, otherwise it will return data with userID=4 OR status=xy
SELECT * FROM `registered_bicycle` WHERE (`userID`='4') AND (
(`status`='In Use')
OR (`status`='Pending')
OR (`status`='Deleted')
)
Try this instead:
SELECT
*
FROM
`registered_bicycle`
WHERE `userID` = '4'
AND `status` IN('In Use','Pending','Deleted')
Your and/or logic got mixed up because of lacking proper parentheses. Also you can use IN instead of multiple OR clauses.
Btw, IN is just the short form of OR
try this:
SELECT * FROM `registered_bicycle`
WHERE (`userID`='4')
AND `status`IN('In Use','Pending','Deleted')

SELECT IF THEN ELSE statement

I want to do query like this
SELECT if(EXISTS(SELECT * FROM application WHERE id_student=1
AND ap_status<>"Wysłano" AND date(app_date) > (SELECT tax_year FROM const_data)),
(SELECT * FROM application WHERE id_student=1 AND ap_status<>"Wysłano" AND date(app_date) > (SELECT tax_year FROM const_data)),
(SELECT * FROM application WHERE id_student=1 AND date(app_date) > (SELECT tax_year FROM const_data)))
But true or false value should contain one column. Is it possible, to make this in other way?
I'm not even sure if what you tried would execute, but this should accomplish what that looks like it is trying to:
SELECT *
FROM application
WHERE id_student=1 AND date(app_date) > (SELECT tax_year FROM const_data)
ORDER BY ap_status="Wysłano"
LIMIT 1
This will fail if const_data has more than one row though.
Edit: Hmm, this answer is not quite right if you expect multiple records. At this point, the best solution is to remove the limit and handle the results in whatever code processes these results. It CAN be done in a single query, but I generally wouldn't recommend it.
Edit2: Sidenote... if app_date is a datetime, you may see performance boosts by removing the use of the DATE() function and instead converting tax_year to a datetime.
Edit3: Last one, I promise.... probably. In the case where it must be done in one query, and results cannot be processed after, this should work.
SELECT *
FROM application
WHERE id_student=1 AND date(app_date) > (SELECT tax_year FROM const_data)
AND IF(EXISTS([that query]), ap_status<>"Wysłano", TRUE)

Use NEWID() without losing distinct?

I am trying to create a new data extract from a (badly designed) sql database. The customer requires that I add a distinctidentifier which I am attempting to do using the NEWID() function. Unfortunately this leads to multiple duplicate records being returned.
After a bit of research I have found that the NEWID() function does indeed 'undo' the use of the distinct keyword, but I cannot work out why or how to overcome this.
An example of the query I am trying to write is as follows:
select distinct
NEWID() as UUID
,Histo_Results_File.ISRN
,Histo_Results_File.Internal_Patient_No
,Histo_Results_File.Date_of_Birth
,Histo_Result_freetext.histo_report
,Histo_Report.Date_Report_Updated as [Investigation_Result_Date]
from apex.Histo_Results_File
inner join apex.Histo_Report on (Histo_Report.Histo_Results_File = Histo_Results_File.ID)
If I miss out the NEWID() line in the select block, I get 569 records returned, which is correct, but if I include that line then I get in excess of 30,000 which are all duplicates of the original 569 but with different IDs. Can anyone suggest a way around this problem?
Thanks in advance
Use a sub query would be the easiest way to do it.
SELECT NEWID() as UUID
, * -- this is everything from below
FROM (
select distinct
Histo_Results_File.ISRN
,Histo_Results_File.Internal_Patient_No
,Histo_Results_File.Date_of_Birth
,Histo_Result_freetext.histo_report
,Histo_Report.Date_Report_Updated as [Investigation_Result_Date]
from apex.Histo_Results_File
inner join apex.Histo_Report on (Histo_Report.Histo_Results_File = Histo_Results_File.ID)) as mySub
select NEWID() as UUID
,ISRN
,Internal_Patient_No
,Date_of_Birth
,histo_report
,Investigation_Result_Date
from (
select distinct
,Histo_Results_File.ISRN
,Histo_Results_File.Internal_Patient_No
,Histo_Results_File.Date_of_Birth
,Histo_Result_freetext.histo_report
,Histo_Report.Date_Report_Updated as [Investigation_Result_Date]
from apex.Histo_Results_File
inner join apex.Histo_Report on (Histo_Report.Histo_Results_File = Histo_Results_File.ID)) t
You can use a sub-query to get around the issue, something like.....
SELECT NEWID() as UUID
,*
FROM (
select distinct
Histo_Results_File.ISRN
,Histo_Results_File.Internal_Patient_No
,Histo_Results_File.Date_of_Birth
,Histo_Result_freetext.histo_report
,Histo_Report.Date_Report_Updated as [Investigation_Result_Date]
from apex.Histo_Results_File
inner join apex.Histo_Report
on (Histo_Report.Histo_Results_File = Histo_Results_File.ID)
) t

Reset a running total if field value is hit

I am able to keep a running total with the below query, and it does that just fine. What I really want, is when the gap field is greater than or equal to the date_diff field, the running total should reset back to the current hrly_qty. I'm sure I could achieve my results with a cursor, but I wanted to know of possible other ways. Ideas?
Example:
WITH CTE AS
(
SELECT a.*, SUM(b.hrly_qty) AS running_total, c.gap
FROM #tmpTrxhist2 a
INNER JOIN #tmpTrxhist2 b ON a.people_id = b.people_id
AND b.sequence_id <= a.sequence_id
INNER JOIN incent_level c ON a.owner_division_id = c.owner_division_id
GROUP BY a.date_diff, a.owner_division_id, a.people_id, a.sequence_id,
a.hrly_qty, c.gap
)
SELECT * FROM CTE
ORDER BY people_id, sequence_id
You seldom need a cursor! A simple case statement should suffice. Of the top of my head something like:
WITH CTE AS
(
SELECT a.*, SUM(b.hrly_qty) AS running_total, c.gap
FROM #tmpTrxhist2 a
INNER JOIN #tmpTrxhist2 b ON a.people_id = b.people_id
AND b.sequence_id <= a.sequence_id
INNER JOIN incent_level c ON a.owner_division_id = c.owner_division_id
GROUP BY a.date_diff, a.owner_division_id, a.people_id, a.sequence_id,
a.hrly_qty, c.gap
)
SELECT *,
CASE
WHEN gap >= date_diff then hrly_qty else gap
END as comp_gap
FROM CTE
ORDER BY people_id, sequence_id
Run the execution plans between the two but SQL is almost always much happier trying to optimise non-cursored code. In my field at least, you usually find cursors are over used and abused by 'proper' C/C++ programmers because they get in their comfort zone when see something that looks a bit like a while-loop rather than think about sets of data. There is a place for cursors, but this isn't it!