Select Statements: Select referring previous select query - mysql

I have two Queries which work independently; I need to combine these results.
Fetch all fields (including wdate and Empid), from Fromdate to ToDate.
Calculate a value (for efficiency, Efc), for a specific wdate and Empid from First Query.
1st Query
SELECT *
FROM tblProductionEffcyDetails
WHERE wDate BETWEEN '06/26/2019' AND '07/25/2019'
AND worker = 'Techn'
ORDER BY Empid, wDate
2nd Query
SELECT Cast(ROUND(SUM(Tstdmin) / NULLIF(SUM(TAvlblmin), 0) * 100,0) as int) AS [Efc]
FROM tblProductionEffcyDetails
WHERE wDate='07/11/2019'
AND Empid='00021'
GROUP BY wdate, Empid
That is, in this 2nd Query, the values for wDate and Empid should come from the results of the 1st Query.
Notes on the data/ table:
Any particular date (wDate) or person (Empid) can have any number
of entries.
Efficiency (Efc) should be given just once per day
(wDate) i.e. it should not have multiple values for a particular wDate.
Table structure is as below
SL wDate Avlbl_Mins NP_Mins Empid Name Process Model Efc
117571 7/13/2019 0 0 21 MARRY Block removing 900-2930 80
117572 7/13/2019 0 0 21 MARRY Microscope checking 900-2929 Null
116872 6/26/2019 430 75 52 SUGANTHI Slab removing 900-2929 75
116873 6/26/2019 0 0 52 SUGANTHI Slab Removing 900-2528 Null

Try this,
you can get the particular Empid set for date between 06/26/2019 and 07/25/2019 using your 1st query and by connecting it to your second query you can sum it up.
SELECT Empid, Cast(ROUND(SUM(Tstdmin) / NULLIF(SUM(TAvlblmin), 0) * 100,0) as int) AS [Efc]
FROM tblProductionEffcyDetails t
WHERE t.Empid in (
SELECT Empid
FROM tblProductionEffcyDetails tb
WHERE tb.wDate BETWEEN '06/26/2019' AND '07/25/2019'
AND tb.worker = 'Techn') and t.wDate BETWEEN '06/26/2019' AND '07/25/2019'
GROUP BY t.wdate, t.Empid
I made the query as I understood your question, let me know if it didn't get the output you want. so I can change the answer.
Hope this helps.

SELECT Empid, Cast(ROUND(SUM(Tstdmin) / NULLIF(SUM(TAvlblmin), 0) * 100,0) as
int) AS [Efc]
FROM (
SELECT *
FROM tblProductionEffcyDetails tb1
WHERE tb1.wDate BETWEEN '06/26/2019' AND '07/25/2019'
AND tb1.worker = 'Techn') as t
GROUP BY t.wdate, t.Empid

Related

How to check how many time a car is parked on

I need a report of which cars (license plates) are parked in and when.
This is an example of my table.
id lic_plate datetime lane
_________________________________________________
10 1234-JM 2022-10-07 12:24:33 IN
11 1234-JM 2022-10-07 12:29:57 OUT
12 5678-PC 2022-10-07 15:14:17 IN
So when I query which are those who are parked more than - for instance - 1hour, the result Now (2022-10-07 15:14:17) should be "5678-PC".
I have tried:
SELECT lic_plate, COUNT(*) AS result
FROM table
GROUP BY lic_plate
HAVING COUNT(lane='IN') AND COUNT(lane='OUT')
But I can't figure out where I insert the HOUR query. And it seems to me that this kind of solution will have some "hidden" flaws.
What will be the best approach?
Thanks in advance.
select max(id) as id
,lic_plate
,max(datetime) as datetime
,timediff(now(),max(datetime)) as time_parked
from t
group by lic_plate
having count(*)%2 != 0
id
lic_plate
datetime
time_parked
12
5678-PC
2022-10-07 15:14:17
69:26:12
Fiddle
We check the time difference between the current date and time and datetime. We count how many records we have per car and if we have even numbers of records we filter the results as we know the car is out already.
select id
,lic_plate
,datetime
,time_parked
from (
select *
,count(*) over(partition by lic_plate) as chk
,timediff(now(),datetime) as time_parked
from t
) t
where chk%2 != 0
id
lic_plate
datetime
time_parked
12
5678-PC
2022-10-07 15:14:17
00:29:58
Fiddle

Average a column based upon the value in another column SQL

Suppose I have the following data
SqlUnixTime BID ASK VALID ASSET_ID
1504900871 101.50 101.6 Y XY1
1504900870 0 101.6 Y XY1
1504900871 101.50 20 N XY1
...
In the BID & ASK columns I can have a valid price, a 0 (meaning no data) or an invalid price (see the final row).
I'd like to compute a 30 day average. I have managed to handle the 0 case using the following query:
Select ASSET_ID, AVG(NULLIF(BID,0)) as AVG_BID_30D, AVG(NULLIF(ASK,0)) as AVG_ASK_30D FROM myDB.myTable where SqlUnixTime > 1504900870 GROUP BY ASSET_ID;
However, how would I only average those values where VALID = "Y". I thought about putting a where clause in the end but then it might not select asset_id that are invalid? I just want it to have a null?
UPDATED
group it by (ASSET_ID, VALID='Y') and then the resultant again group by VALID='Y'
I think it will work.
select A.ASSET_ID, A.AVG_BID_30D, A.AVG_ASK_30D
from (Select ASSET_ID, AVG(NULLIF(BID,0)) as AVG_BID_30D, AVG(NULLIF (ASK,0)) as AVG_ASK_30D, VALID
FROM myDB.myTable where SqlUnixTime > 1504900870
GROUP BY ASSET_ID, VALID='Y') as A
group by ASSET_ID='Y';
.

Mysql single column result to multiple column result

I have a problem with a MySQL query, the problem is I have the following table:
id, rep, val dates
1 rep1 200 06/01/2014
2 rep2 300 06/01/2014
3 rep3 400 06/01/2014
4 rep4 500 06/01/2014
5 rep5 100 06/01/2014
6 rep1 200 02/06/2014
7 rep2 300 02/06/2014
8 rep3 900 02/06/2014
9 rep4 700 02/06/2014
10 rep5 600 02/06/2014
and I want a result like this:
rep 01/06/2014 02/06/2014
rep1 200 200
rep2 300 300
rep3 400 900
rep4 500 700
rep5 100 600
thank you very much!
You seem to want the most recent row for each rep. Here is an approach that often performs well:
select t.*
from table t
where not exists (select 1
from table t2
where t2.repid = t.repid and
t2.id > t.id
);
This transforms the problem to: "Get me the rows in table t where there is no other row with the same repid and a larger id." That is the same logic as getting the last one, just convoluted a bit to help the database know what to do.
For performance reasons, an index on t(repid, id) is helpful.
You seem to want the val for each of the dates.
Assuming the dates you are interested in are fixed then you can do that as follows. For output date column you check of the row matches the date for that column. If so you use the value of val , if not you just use 0. Then you sum all the resulting values, grouping by rep. I have assumed a fixed format of date.
SELECT rep, SUM(IF(dates='2014/06/01'), val, 0) AS '2014/06/01', SUM(IF(dates='2014/06/02'), val, 0) AS '2014/06/02'
FROM sometable
GROUP BY rep
Or if you just wanted the highest val for each day
SELECT rep, MAX(IF(dates='2014/06/01'), val, 0) AS '2014/06/01', MAX(IF(dates='2014/06/02'), val, 0) AS '2014/06/02'
FROM sometable
GROUP BY rep
If the number of dates is variable then not really a direct way to do it (as the number of resulting columns would vary). It would be easiest to do this manly in your calling script based on the following, giving you one row per rep / possible date with a sum of the values of val for that rep / date combination:-
SELECT rep, sub0.dates, SUM(IF(sometable.dates=sub0.dates), val, 0)
FROM sometable
CROSS JOIN
(
SELECT DISTINCT dates
FROM sometable
) sub0
GROUP BY rep, sub0.dates

Why does the total from my query results not add up?

I have three queries that get stats from the database, but the total does not add up correctly for my results. If I do the math myself this is what I get: // 440728 / 1128 = 390.72
However, the following is what is returned by my queries:
SELECT * FROM facebook_accts
WHERE user_id IN (SELECT id FROM `user_accts` WHERE owner_id = '121')
// returns 1128
SELECT sum(friend_count) FROM facebook_accts
WHERE user_id IN
(SELECT id FROM `user_accts` WHERE owner_id = '121')
// returns 440728
SELECT avg(friend_count) FROM facebook_accts
WHERE user_id IN
(SELECT id FROM `user_accts` WHERE owner_id = '121')
// returns 392.11 (number formatted to two decimal places by php)
this may be happening because of column friend_count having some NULL values because SUM and AVG sunctions ignore NULL values. see here.
I guess the 1128 rows contain NULL values (which AVG and SUM ignore).

Break Numbers List Into Min and Max Ranges

Brain is not working today and my google skills are failing me.
I have a column of numbers ranging from 1 - 1000. I want to dump the min and max values for 100 (or whatever I chose) record ranges into a temp table. The plan is to use this temp table to process ranges of records (in this example 100 at a time) in a larger table.
Swear I have done this before with a CTE but then I had something to group on. Here I just want to break up a single list of numbers into ranges of X.
The output from the temp table should look like:
Min Max
0 99
100 199
200 299
300 399
etc.
Thanks!
You can use this trick from Stuart Ainsworth:
http://codegumbo.com/index.php/2009/01/25/building-ranges-using-a-dynamically-generated-numbers-table/
Numbers tables are awesome, but he uses a dynamically generated numbers table, which is even awesome...r.
If you know all numbers are present in the source table, you can use a recursive CTE to generate the number ranges:
; with numbers as
(
select 0 as a
, 99 as b
union all
select a+100
, b+100
from numbers
where a < 900
)
select *
from numbers
If the source table is sparsely populated, you can limit it to numbers that are actually present like:
... insert CTE from above here ...
select min(ot.NumberColumn)
, max(ot.NumberColumn)
from numbers
left join
OtherTable ot
on ot.NumberColumn between numbers.a and numbers.b
group by
numbers.a
enter code hereI have been having a play with a CTE after you posted this and came up with the following, I would be interested to hear if it works for you at all.
DECLARE #segment int = 100
;
WITH _CTE
(rowNum, value)
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY col01) -1, col01
FROM dbo.testTable
)
SELECT rowNum/#segment AS Bucket, MIN(Value) AS MinVal, MAX(Value) AS MaxVal
FROM _CTE
group by rowNum/#segment
ORDER BY Bucket
;
col01 in this case is the column that you want the min/max range values from, as is TestTable.