Compare output of select statement - mysql

My Table1
| Participantsid | Validfrom | Validto |
| 2,4,1 | 2016-02-21 10:22:00 | 2016-02-21 12:22:00 |
| 2,4,1 | 2016-03-04 10:00:00 | 2016-03-04 10:25:00 |
| 2,3,4,1 | 2016-02-19 10:43:00 | 2016-02-19 11:08:00 |
| 2,3,4,1 | 2016-02-22 11:32:00 | 2016-02-22 11:57:00 |
| 4,6,5 | 2016-02-20 17:00:00 | 2016-02-20 18:00:00 |
| 1,2,5 | 2016-02-22 18:00:00 | 2016-02-22 19:00:00 |
| 2,3,6,1 | 2016-03-23 10:00:00 | 2016-03-23 11:00:00 |
| 1,2,3,5 | 2016-02-20 12:00:00 | 2016-02-20 14:00:00 |
| 2,6 | 2016-02-20 12:00:00 | 2016-02-20 13:00:00 |
Another Table2
+--------------+------------+
| EmployeeName | EmployeeID |
+--------------+------------+
| Mathews | 1 |
| Gerald | 2 |
| Bravo | 3 |
| Smith | 4 |
| George | 5 |
| Bailey | 6 |
| Stephen | 9 |
| Balu c | 10 |
I have some inputid's=1,5,6.
Now I have to compare this input id's with Participantsid from table1 for a given validfrom and validto date and if there is a match I need to get the name corresponding to that id.
Emaple:- inputid's=1,2,3 for from- 2016-02-22 18:00:00, to-2016-02-22 19:00:00
it should give me o/p =mathews,gerald
I am currently writing two select statements and using one for loop which gives me the result but its wrong
I am trying to do it in a single query but no way near to my required output.please help

Desired result can be achieved by using group_concat and find_in_set with sub-query.
SQLFiddle:
http://sqlfiddle.com/#!9/ce893/1
select group_concat(EmployeeName) as `o/p`
from Table2
where FIND_IN_SET(EmployeeID,
(select Participantsid from Table1
where Validfrom = '2016-02-22 18:00:00' and Validto = '2016-02-22 19:00:00'));

Related

Left join tables on nearest datetime without duplicating values

I am attempting to join table_a and table_b together on their nearest/closest datetime fields (date_a and date_b), but I am wanting to ensure that I do not receive duplicate values from table_b for each joined row. If the available date_b rows from table_b are used up on closer table_a values, then the joined row should just remain blank.
Another way of putting it: the datetime values from table_b can only be used once, and they should only be used on the absolute closest/nearest value from table_a.
Here's an example of table_a:
| entry_a | date_a |
|---------|---------------------|
| 1 | 2019-02-20 01:05:00 |
| 2 | 2019-02-20 01:10:00 |
| 3 | 2019-02-21 01:15:00 |
| 4 | 2019-02-22 01:20:00 |
| 5 | 2019-02-23 01:25:00 |
| 6 | 2019-02-24 01:30:00 |
| 7 | 2019-02-25 01:35:00 |
| 8 | 2019-02-26 01:40:00 |
| 9 | 2019-02-27 01:45:00 |
| 10 | 2019-02-28 01:50:00 |
Here's table_b:
| entry_b | date_b | filename |
|---------|---------------------|----------------|
| 1 | 2019-02-20 01:03:00 | 20190220010300 |
| 2 | 2019-02-20 01:07:00 | 20190220010700 |
| 3 | 2019-02-23 01:23:00 | 20190223012300 |
| 4 | 2019-02-24 01:26:00 | 20190224012600 |
| 5 | 2019-02-25 01:30:00 | 20190225013000 |
| 6 | 2019-02-26 01:34:00 | 20190226013400 |
| 7 | 2019-02-27 01:40:00 | 20190227014000 |
| 8 | 2019-02-28 01:50:00 | 20190228015000 |
| 9 | 2019-02-28 01:51:00 | 20190228015100 |
And here's the desired result:
| entry_a | date_a | entry_b | date_b | filename |
|---------|---------------------|---------|---------------------|----------------|
| 1 | 2019-02-20 01:05:00 | 1 | 2019-02-20 01:03:00 | 20190220010300 |
| 2 | 2019-02-20 01:10:00 | 2 | 2019-02-20 01:07:00 | 20190220010700 |
| 3 | 2019-02-21 01:15:00 | (null) | (null) | (null) |
| 4 | 2019-02-22 01:20:00 | 3 | 2019-02-23 01:23:00 | 20190223012300 |
| 5 | 2019-02-23 01:25:00 | 4 | 2019-02-24 01:26:00 | 20190224012600 |
| 6 | 2019-02-24 01:30:00 | 5 | 2019-02-25 01:30:00 | 20190225013000 |
| 7 | 2019-02-25 01:35:00 | 6 | 2019-02-26 01:34:00 | 20190226013400 |
| 8 | 2019-02-26 01:40:00 | 7 | 2019-02-27 01:40:00 | 20190227014000 |
| 9 | 2019-02-27 01:45:00 | 8 | 2019-02-28 01:50:00 | 20190228015000 |
| 10 | 2019-02-28 01:50:00 | 9 | 2019-02-28 01:51:00 | 20190228015100 |
One thing to particularly note in the desired result: the last two rows show that date_b.8 and date_a.10 match exactly ... but if date_b.8 and date_a.9 are allowed to match, then date_b.9 and date_a.10 can match on something fairly close, also. (If this is an impossible complication, I understand. It's not critical. What's more important is the situation illustrated in rows 2-4 of the result_table.)
I am using MySQL 5.6. I've built a SQL fiddle here with the tables loaded up: DEMO
Thank you all very kindly for your help and for the many answers you've provided to guide me over the years.

MYSQL: Display one query from a select statement from two unrelated tables

I'm trying to display the sum of monthly revenue from different unrelated tables, Where i display the budgeted against the actual usage
I have two tables Planned Budget and actual budget, with with similar columns but different data, in a query i want retrieve the sum of budget and group it Yearly and monthly.
Planned Budget table
+-----+-------+-------------+-------------+
| uid | codes | opca_budget | date_period |
+-----+-------+-------------+-------------+
| 10 | 3210 | 3000 | 2018-03-01 |
| 17 | 3355 | 3000 | 2018-03-01 |
| 33 | 3210 | 4000 | 2018-04-01 |
| 40 | 3355 | 4000 | 2018-04-01 |
| 56 | 3210 | 5000 | 2018-05-01 |
| 63 | 3355 | 5000 | 2018-05-01 |
| 79 | 3210 | 6000 | 2018-06-01 |
| 86 | 3355 | 6000 | 2018-06-01 |
| 109 | 3355 | 45000 | 2018-07-01 |
Actual Budget
+-----+-------+-------------+---------------------+
| uid | codes | opca_budget | date_period |
+-----+-------+-------------+---------------------+
| 10 | 3210 | 6500 | 2018-03-01 00:00:00 |
| 17 | 3355 | 6500 | 2018-03-01 00:00:00 |
| 18 | 3120 | 6500 | 2018-03-01 00:00:00 |
| 33 | 3210 | 7500 | 2018-04-01 00:00:00 |
| 40 | 3355 | 7500 | 2018-04-01 00:00:00 |
| 41 | 3120 | 7500 | 2018-04-01 00:00:00 |
| 56 | 3210 | 8500 | 2018-05-01 00:00:00 |
| 63 | 3355 | 8500 | 2018-05-01 00:00:00 |
| 64 | 3120 | 8500 | 2018-05-01 00:00:00 |
I tried to combine them horizontally, But i get wrong results
SELECT YEAR(c.date_period)
, MONTH(c.date_period)
, SUM(c.opca_budget) MonthlyBudget
, SUM(a.opca_budget) MonthlyUsage
FROM opexcapex c
LEFT
JOIN opxcpx_actuals a
ON YEAR(c.date_period) = YEAR(a.date_period)
AND MONTH(c.date_period) = MONTH(a.date_period)
WHERE c.date_period BETWEEN '2018-03-01' AND '2019-02-29'
GROUP
BY YEAR(c.date_period)
, MONTH(c.date_period);
+------+-------+---------------+--------------+
| Year | Month | MonthlyBudget | MonthlyUsage |
+------+-------+---------------+--------------+
| 2018 | 3 | 168000 | 364000 |
| 2018 | 4 | 224000 | 420000 |
| 2018 | 5 | 280000 | 476000 |
| 2018 | 6 | 336000 | 532000 |
| 2018 | 7 | 2520000 | 588000 |
| 2018 | 8 | 576000 | 367200 |
| 2018 | 9 | 3240000 | 367200 |
| 2018 | 10 | 720000 | 252000 |
| 2018 | 11 | 792000 | 1807200 |
| 2018 | 12 | 2583000 | 1323000 |
| 2019 | 1 | 9000 | NULL |
| 2019 | 2 | 36000 | NULL |
+------+-------+---------------+--------------+
I expect to get results like this:
+-----------+-------------+---------------+--------------+
| BudgtYear | BudgetMonth | MonthlyBudget | MonthlyUsage |
+-----------+-------------+---------------+--------------+
| 2018 | 3 | 24000 | 45500 |
| 2018 | 4 | 32000 | 52500 |
| 2018 | 5 | 40000 | 59500 |
| 2018 | 6 | 48000 | 66500 |
| 2018 | 7 | 360000 | 73500 |
| 2018 | 8 | 72000 | 40800 |
| 2018 | 9 | 405000 | 40800 |
| 2018 | 10 | 90000 | 28000 |
| 2018 | 11 | 99000 | 200800 |
| 2018 | 12 | 369000 | 147000 |
| 2019 | 1 | 9000 | |
| 2019 | 2 | 36000 | |
+-----------+-------------+---------------+--------------+
You want to do a UNION ALL as a sub-query and then calculate the sum on the value from that sub-query, notice also that I use two amount columns in the union but one is always null, this is to have the two selects return the same number of columns but separated values
SELECT YEAR(date_period) as year, MONTH(date_period) as month, SUM(mbudget) AS MonthlyBudget, SUM(musage) as MonthlyUsage
FROM (SELECT date_period, opca_budget mbudget, null musage
FROM opexcapex
UNION ALL
SELECT date_period, null, opca_budget
FROM opxcpx_actuals
) sq
WHERE date_period BETWEEN '2018-03-01' AND '2019-02-29'
GROUP BY year, month
You should be able to UNION the 2 tables first, then SELECT from the resulting data, something like this (Updated query) :-
SELECT YEAR(date_period), MONTH(date_period), MonthlyBudget, MonthlyUsage
FROM
(SELECT date_period, opca_budget as MonthlyBudget, 0 as MonthlyUsage FROM
opexcapex
UNION
SELECT date_period, 0 as MonthlyBudget, opca_budget as MonthlyUsage FROM
opxcpx_actuals) T1
WHERE date_period BETWEEN '2018-03-01' AND '2019-02-29'
GROUP BY YEAR(date_period), MONTH(date_period);

sql - count of two colums

i put in a database many line and i have this :
+----+---------------------+-------------+----------------+-----------+
| ID | time | os_name | program | last_line |
+----+---------------------+-------------+----------------+-----------+
| 14 | 2019-01-04 14:00:00 | titi | roro | 109 |
| 15 | 2019-01-04 14:00:00 | titi | roro | 109 |
| 16 | 2019-01-04 14:00:00 | gege | fefe | 109 |
i want :
+---------------------+-------------------------+-------------+-----------+-----------+
| time | nb_os_name_program | os_name | program | last_line |
+---------------------+-------------------------+-------------+-----------+-----------+
| 2019-01-04 14:00:00 | 2 | titi | roro | 109 |
| 2019-01-04 14:00:00 | 1 | gege | fefe | 109 |
Simple GROUP BY with aggregation would help you :
SELECT time, os_name, count(*) as nb_os_name, program, lastline,
FROM table t
GROUP BY time, os_name, program, lastline

mysql: how to get the last value of one spesific column as part of the subquery

I have the following table.
+--------------------+--------+------+------------+----------+---------------------+
| StopAddress | UserID | Name | StartHours | EndHours | SamplingEnd |
+--------------------+--------+------+------------+----------+---------------------+
| Legends | 1 | Lisa | 09:00:00 | 08:00:59 | 2016-03-22 09:00:00 |
| 26 Bluewater Drive | 1 | Lisa | 10:00:00 | 08:00:59 | 2016-03-22 10:00:00 |
| Walker Drive | 1 | Lisa | 11:00:00 | 08:00:59 | 2016-03-22 11:00:00 |
| Blouberg | 1 | Lisa | 12:00:00 | 08:00:59 | 2016-03-22 12:00:00 |
| William Moffet | 1 | Lisa | 13:00:00 | 08:00:59 | 2016-03-22 13:00:00 |
| Paterson | 1 | Lisa | 14:00:00 | 08:00:59 | 2016-03-22 14:00:00 |
| 70 Kings Street | 1 | Lisa | 15:00:00 | 08:00:59 | 2016-03-22 15:00:00 |
| Pick n Pay | 1 | Lisa | 16:00:00 | 08:00:59 | 2016-03-22 16:00:00 |
| Mars | 1 | Lisa | 17:00:00 | 08:00:59 | 2016-03-22 17:00:00 |
| Club Shakes | 1 | Lisa | 18:00:00 | 08:00:59 | 2016-03-22 18:00:00 |
| Stones | 1 | Lisa | 19:00:00 | 08:00:59 | 2016-03-22 19:00:00 |
| Ermelo | 1 | Lisa | 20:00:00 | 08:00:59 | 2016-03-22 20:00:00 |
| Angelos | 1 | Lisa | 05:00:00 | 00:20:16 | 2016-03-23 05:00:00 |
| Game | 1 | Lisa | 05:00:00 | 00:20:16 | 2016-03-23 04:00:00 |
+--------------------+--------+------+------------+----------+---------------------+
When I run the following query, I get the result below. (See "Current result" )
QUERY:
SELECT Min(samplingend) AS StartTime,
Min(starthours) AS StartHours,
Max(endhours) AS EndHours,
Max(samplingend) AS LastStart,
(SELECT stopaddress
FROM table1
ORDER BY samplingend DESC
LIMIT 1) AS StopAddress
FROM table1
GROUP BY userid,
name,
Date(samplingend)
ORDER BY Date(samplingend),
userid;
CURRENT RESULT:
+---------------------+------------+----------+---------------------+-------------+
| StartTime | StartHours | EndHours | LastStart | StopAddress |
+---------------------+------------+----------+---------------------+-------------+
| 2016-03-22 09:00:00 | 09:00:00 | 08:00:59 | 2016-03-22 20:00:00 | Angelos |
| 2016-03-23 04:00:00 | 05:00:00 | 00:20:16 | 2016-03-23 05:00:00 | Angelos |
+---------------------+------------+----------+---------------------+-------------+
DESIRED RESULT:
When you run the query it must give the StopAddress WHERE StopAddress = Max(SamplingEnd) grouped per day. e.g. On the 22nd StopAddress should = "Ermelo" and on the 23rd = Angelos in the example below. Is it possible to achieve this result by altering the code ONLY in LINE6 WITHOUT USING Table Aliases. e.g by not using table1 T1 or T2? Line 6: (SELECT StopAddress from table1 order by SamplingEnd DESC limit 1) AS StopAddress)
Example of outcome: (Look at the StopAddress Column)
+---------------------+------------+----------+---------------------+-------------+
| StartTime | StartHours | EndHours | LastStart | StopAddress |
+---------------------+------------+----------+---------------------+-------------+
| 2016-03-22 09:00:00 | 09:00:00 | 08:00:59 | 2016-03-22 20:00:00 | Ermelo |
| 2016-03-23 04:00:00 | 05:00:00 | 00:20:16 | 2016-03-23 05:00:00 | Angelos |
+---------------------+------------+----------+---------------------+-------------+
Thanks for your time!!
You need to include table alias to use the external value
SELECT Min(samplingend) AS StartTime,
Min(starthours) AS StartHours,
Max(endhours) AS EndHours,
Max(samplingend) AS LastStart,
(SELECT T2.stopaddress
FROM table1 T2
WHERE Date(T2.samplingend) = Date(T1.samplingend) -- ADD THIS WHERE
ORDER BY T2.samplingend DESC
LIMIT 1) AS StopAddress
FROM table1 T1
GROUP BY userid,
name,
Date(samplingend)
ORDER BY Date(samplingend),
userid;
Try this:
SELECT StartTime, StartHours, EndHours, LastStart,
(SELECT StopAddress
FROM table1 AS t2
WHERE t1.UserID = t2.UserID AND
t1.Name = t2.Name AND
t2.SamplingEnd = t1.LastStart
LIMIT 1) AS StopAddress
FROM (
SELECT UserID, Name,
MIN(SamplingEnd) AS StartTime,
MIN(StartHours) AS StartHours,
MAX(EndHours) AS EndHours,
MAX(SamplingEnd) AS LastStart
FROM table1
GROUP BY UserID, Name, DATE(SamplingEnd)) AS t1
The idea is to wrap your query in subquery and in the outer query use a correlated subquery using the value of LastStart in order to get the StopAddress.
Demo here

MySQL last value of day

I am trying to construct a query that produces one value per day and I want that value to be the last recorded value of the day. This is what my table looks like (actual dataset contains a row for each minute):
+------------+----------+-------+
| Date | Time | Value |
+------------+----------+-------+
| 2015-06-14 | 13:00:00 | 3 |
| 2015-06-14 | 14:00:00 | 5 |
| 2015-06-15 | 11:00:00 | 6 |
| 2015-06-15 | 17:00:00 | 9 |
| 2015-06-16 | 09:00:00 | 2 |
| 2015-06-16 | 10:00:00 | 4 |
+------------+----------+-------+
I would like the outcome of the query to look like this:
+------------+----------+-------+
| Date | Time | Value |
+------------+----------+-------+
| 2015-06-14 | 14:00:00 | 5 |
| 2015-06-15 | 17:00:00 | 9 |
| 2015-06-16 | 10:00:00 | 4 |
+------------+----------+-------+
What would the SQL-statement need to be to retrieve this result? Any help is much appreciated!
select t1.date,
t1.time,
t1.value
from table t1
where t1.time= (select max(t2.time)
from table t2
where t2.date = t1.date);