MySQl v5.6 How to exclude unwanted / incorrect rows produced after Joining two tables - mysql

I have two tables , I want to fetch correct data rows, but when I make a join in between incorrect extra rows are getting create. I want to exclude them.
Table T1
Employee_ID
Work_START
1111
10 Nov
1111
14 Nov
1111
18 Nov
Table T2
Employee_ID
Work_END
1111
12 Nov
1111
15 Nov
1111
20 Nov
I can not use Rank Function since MySQL version is 5.6 and I have Read access to DB so can not create INDEX or use SET function
I tried to make a join with Below SQL Query:
Select T1.Employee_ID, T1.Work_START, T2.Work_END from T1
Left Join T2 On T1.Employee_ID = T2.Employee_ID
where T2.Work_END > T1.Work_START
(used this condition to reduce the incorrect joined rows)
I tried using Left , Right join, using Distinct function as well
I am getting the result as below
Order_ID
Order_Date
Ship_Date
1111
10 Nov
12 Nov
1111
10 Nov
15 Nov
1111
10 Nov
20 Nov
1111
14 Nov
15 Nov
1111
14 Nov
20 Nov
1111
18 Nov
20 Nov
Expected Result is as below
Logic of Output : an employee has worked on a task on 3 different times, so to get those correct 3 rows I want the expected table to follow the below condition
row 1 work_END should be higher than row 1 Work_START and
2nd row Work_START should be higher than 1st row Work_END and so on
next row Work_start should be higher than previos row Work_END
Expected Table
Order_ID
Order_Date
Ship_Date
1111
10 Nov
12 Nov
1111
14 Nov
15 Nov
1111
18 Nov
20 Nov
Please Note: I Have read access to DB and Can not use Rank function since MySQL version is 5.6

Disclaimer : you should consider fixing your data model. Spreading that data over two different tables does not look like appropriate design.
With the current data model, we could approach the question like so: starting from each beginning date in the first table, bring the closest end date with a subquery:
select t1.employee_id, t1.work_start,
(
select min(t2.work_end)
from t2
where t2.employee_id = t1.employee_id and t2.work_end > t1.work_start
) work_end
from t1
This guarantees as many rows in the resultset as there are in the first table (not more, not less). If the dates of the two tables do not properly interleave, you might see results that look inconsistent somehow (using row_number() would not avoid this).

Related

MySQL Use Distinct or Group By in XREF Table Query

I'm building a php configurator with a series of relationships which I'm controlling with MySQL XREF tables.
There is one XREF table which has multiple dependencies as below:
Table: cto_body_deck_rear_chassis_xref
body_id
deck_type_id
rear_id
chassis_id
22
20
23
13
23
20
18
17
23
20
21
17
23
20
24
17
24
20
18
17
25
21
22
14
Each complete combination is unique although there are similarities between columns; however, I'm getting a duplication problem when selecting from a deck type table, relative to a body id variable passed in the URL.
Table: cto_deck_type
deck_type_id
deck_type_content
20
Single Deck
21
3/4 Length Fixed 2nd Deck
22
Full Length Fixed 2nd Deck
If I use the following MySQL statement:
SELECT d.deck_type_id, d.deck_type_content
FROM cto_deck_type d
LEFT JOIN cto_body_deck_rear_chassis_xref xref
ON xref.deck_type_id = d.deck_type_id
WHERE xref.body_id = 23
I get 3 results, even though each result is identical because the body_id and deck_type_id match 3 times (20).
If the results are identical, I want to group them together or select distinct but I'm not sure what the statement should look like?
Any assistance would be appreciated.
SELECT d.deck_type_id, d.deck_type_content
FROM cto_deck_type d
LEFT JOIN cto_body_deck_rear_chassis_xref xref
ON xref.deck_type_id = d.deck_type_id
WHERE xref.body_id = 23
;; and add the line
GROUP BY d.deck_type_id, d.deck_type_content

Two Table columns into one Query

I'm trying to bring data from two different columns into one query field. Example: Table1 [Field1] and [Field2]. I don't know if that's possible but in my Query I'm trying to bring the datas from these two Fields and show into one in Query. e.g.
|Table|
|DepartureDate1 | DepartureDate2|
| 15 Nov 2021 | 20 Nov 2021 |
|Query|
|DepartureDate1&2|
15 Nov 2021
20 Nov 2021
Thank you in advance.
Try using a UNION.
SELECT DepartureDate1 AS [DepartureDate] FROM Table1
UNION
SELECT DepartureDate2 AS [DepartureDate] FROM Table1

Missing values on count in mysql

I'm just stuck with this issue atm and I'm not 100% sure how to deal with it.
I have a table where I'm aggregating data on week
select week(create_date),count(*)
from user
where create_date > '2015-02-01'
and id_customer between 9 and 17
group by week(create_date);
the results that I'm getting have missing values in the count, as shown below
5 334
6 376
7 394
8 405
9 504
10 569
11 709
12 679
13 802
14 936
15 1081
16 559
21 1
24 9
25 22
26 1
32 3
34 1
35 1
For example here from 16 to 21 there a obviously 4 values missing I would like these values to be included and count to be 0. I want this because I want the weeks to be matching with other metrics as we are outputting them in an excel file for internal analysis.
Any help would be greatly appreciated.
The problem is that an sql query cannot really produce data that is not there at all.
You have 3 options:
If you have data for each week in your entire table for the period you are querying, then you can use a self join to get the missing weeks:
select week(t1.create_date), count(t2.id_customer)
from customer t1
left join customer t2 on t1.id_customer=t2.id_customer and t1.create_date=t2.create_date and t2.id_customer between 9 and 17
where t1.create_date > '2015-02-01'
group by week(t1.create_date)
If you have missing weeks from the customer table as whole, then create a helper table that contain week numbers from 1 or 0 (depending on mysql config) to 53 and do a left join to this helper table.
Use a stored procedure that loops through the results of your original query and inserts the missing data in the resultset using a temporary table and then returns the extended dataset as result.
The problem is that there is no data matching your criteria for the missing weeks. A solution will be to join from a table that has all week numbers. For example if you create a table weeknumbers with one field weeknumber containing all the numbers from 0 to 53 you can use something like this
select weeknumber,count(user.*)
from weeknumbers left join user on (weeknumbers.weeknumber=week(user.create_date)
and user.create_date > '2015-02-01'
and user.id_customer between 9 and 17)
group by weeknumber;
Additionaly you might want to limit the week numbers you do not want to see.
The other way is to do it in the application.

Does any way to get the last inserted values in each days

id date calls
5 2015-02-17 01:06:01 1
6 2015-02-17 11:07:01 2
7 2015-02-17 23:06:01 3
8 2015-02-18 03:07:01 1
9 2015-02-18 09:06:01 2
10 2015-02-18 17:07:01 3
11 2015-02-18 22:06:01 4
12 2015-02-19 01:07:01 1
13 2015-02-19 08:06:01 2
14 2015-02-19 18:07:01 3
15 2015-02-19 23:06:01 4
my table structure is like this and I need to calculate the sum of call in each days. In this table, you can see that, the last call in feb 17 was at 23:06:01 and call count was 3. In feb 18 was at 22:06:01 and call count was 4. Can I get the sum of all this last call counts of each day.
You can use a subquery to determine which rows to sum (the ones matching the last call for each date, using MySQL it would be:
select sum(calls) sum_last_calls
from your_table
where `date` in (
select max(date) max_date
from your_table
group by date(`date`)
)
This query will return 11 as the sum (from 3+4+4).
The date() function used in the subquery is specific to your database and might need to be changed according to your specific database syntax - the point is that it should return the date without time (it could be date::date (Postgresql) or cast(date as date) (MSSQL and others)).
Sample SQL Fiddle for MySQL and Postgresql
Postgresql version:
select sum(calls) as calls
from (
select max(calls) as calls
from t
where date::date between '2015-02-17' and '2015-02-19'
group by date::date
) s

MS Access "double counting" in a query of queries

Apologies if this question is a bit long, but I wanted to explain in detail what it is I am trying to do.
I am developing a database in MS Access 2010/Windows 7 which analyses and reports on incidents (e.g. faults) in an organisation. An incident is reported as beginning at a particular date/time in a particular location for a particular duration. An incident may occasionally cause one or more "live resilience outages" (LRO) which will have the same start-time but can be in different locations and have different durations. So for example a router going out of service in the central technical area for 600 sec might cause live outages of 60 sec and 30 sec in studios 5 and 6 respectively.
I need to report on three date ranges: the month in question, the previous month and the (financial, beginning in April) year to date. So for example the report for March 2012 would consider the periods 01 Mar 2012 - 31 Mar 2012 (month), 01 Feb 2012 - 29 Feb 2012 (previous) and 01 Apr 2011 - 31 Mar 2012 (YTD).
These dates are correctly calculated in a form called ReportCentre. I have three queries to return the LROs for the different date ranges: QueryLROMonth, QueryLROPrevious and QueryLROYTD all of which work properly in isolation (i.e. return the correct values). So for example QueryLROMonth is defined as
SELECT lro.*
FROM lro INNER JOIN incidents ON lro.pid = incidents.id
WHERE (((incidents.begin) Between [Forms]![ReportCentre].[StartMonth] And
[Forms]![ReportCentre].[EndMonth]));
which returns the expected values:
id pid duration facility
6 681 30 23
7 686 857 23
8 735 600 25
9 738 600 25
as does the YTD query
id pid duration facility
1 100 120 25
2 366 5 25
3 380 460 1
4 505 341 23
5 622 0 29
6 681 30 23
7 686 857 23
8 735 600 25
9 738 600 25
20 1297 50 1
So far so good, but now the bit that's got me puzzled. I am trying to design another query which takes the output of the three LRO queries (and some other data), groups it all by facility and calculates things like availability. If I design a totals query and include the Facilities table (for the facility name) and the QueryLROMonth query e.g.
SELECT facilities.facility, Count(QueryLROMonth.id) AS lrocountmonth, Sum(QueryLROMonth.duration) AS lrosecondsmonth
FROM QueryLROMonth INNER JOIN facilities ON QueryLROMonth.facility = facilities.ID
GROUP BY facilities.facility;
This works fine and produces what I expect.
facility lrocountmonth lrosecondsmonth
HQ3 2 887
HQ5 2 1200
but as soon as I introduce the YTD query:
SELECT facilities.facility, Count(QueryLROMonth.id) AS lrocountmonth, Sum(QueryLROMonth.duration) AS lrosecondsmonth, Count(QueryLROYTD.id) AS lrocountytd, Sum(QueryLROYTD.duration) AS lrosecondsytd
FROM QueryLROYTD INNER JOIN (QueryLROMonth INNER JOIN facilities ON QueryLROMonth.facility = facilities.ID) ON QueryLROYTD.facility = facilities.ID
GROUP BY facilities.facility;
for some reason stuff starts being counted reported wrongly. Specifically the two Count columns are multiplied together and so lrocountmonth and lrosecondsmonth are both multiplied by lrocountytd. Similarly lrocountytd and lrosecondsytd are both multiplied by lrocountmonth.
facility lrocountmonth lrosecondsmonth lrocountytd lrosecondsytd
HQ3 6 2661 6 2456
HQ5 8 4800 8 2650
What am I doing wrong? How do I prevent this entanglement?
Your [QueryLROMonth] and [QueryLROYTD] queries each return multiple rows per Facility, but because you are effectively JOINing them on just the Facility_ID you are producing an OUTER JOIN of sorts. For example, if for a given Facility your [Month] query contains 3 rows and your [YTD] query contains 6 rows then your JOIN on Facility_ID alone will produce 18 rows.
You'll want to create aggregation queries that "roll up" the Monthly and YTD numbers by Facility first, so they each have only one row per Facility. You can then use them in your final query to produce the report.
Troubleshooting tip: If your aggregation queries are producing strange results try removing the GROUP BY parts so you can see the underlying rows that are being aggregated.