I have two tables e_sku and e_availability, In e_sku table i have 45 rows with the default availability as 1, below is an example
id is_available name
1 1 UN001N
2 1 UN002N
3 1 UN003N
4 1 UN004N
5 1 UN005N
6 1 UN006N
7 1 UN007N
8 1 UN008N
9 1 UN009N
10 1 UN010N
11 1 UN011N
12 1 UN012N
13 1 UN013N
14 1 UN014N
15 1 UN015N
16 1 UN016N
17 1 UN017N
18 1 UN018N
19 1 UN019N
20 1 UN020N
21 1 UN021N
22 1 UN022N
23 1 UN023N
24 1 UN024N
25 1 UN025N
26 1 UN026N
27 1 UN027N
28 1 UN028N
29 1 UN029N
30 1 UN030N
31 1 UN031N
32 1 UN032N
33 1 UN033N
34 1 UN034N
35 1 UN035N
36 1 UN036N
37 1 UN037N
38 1 UN038N
39 1 UN039N
40 1 UN040N
41 1 UN041N
42 1 UN042N
43 1 UN043N
44 1 UN044N
45 1 UN045N
Second table is e_availability in this table i am only storing the unavailability with dates below is the example
id e_sku_id is_available working_date
1 5 0 10/20/2016
2 8 0 10/20/2016
3 10 0 10/20/2016
4 1 0 10/20/2016
5 15 0 10/20/2016
6 11 0 10/19/2016
7 1 0 10/19/2016
Because the data is capturing every date for unavailability so i am only gathering the unavailable product's data in e_availability table w.r.t. dates, Now i am looking to show the data for each day as complete skus in such a way that every day report will show 45 skus and for available sku it will show 1 from e_sku table's column is_available and for unavailable sku it will show the column of is_availability from e_availability table
I am using mysql database, I tried many join queries but not getting the report.
can any one guide about which join i require
I got the result by using this query
SELECT * FROM (SELECT id,NAME,1 AS is_available FROM e_sku
WHERE company_id = 2
AND id NOT IN (SELECT id FROM (SELECT e_sku.id,e_sku.name, edge_availability.is_available FROM edge_availability
JOIN edge_working ON edge_working.`id` = edge_availability.`working_id`
JOIN e_sku ON e_sku.id = edge_availability.`sku_id`
WHERE edge_working.`working_date` = '2016-10-19' AND edge_availability.`store_id` = 84) X)
UNION
SELECT e_sku.id,e_sku.name, edge_availability.is_available FROM edge_availability
JOIN edge_working ON edge_working.`id` = edge_availability.`working_id`
JOIN e_sku ON e_sku.id = edge_availability.`sku_id`
WHERE edge_working.`working_date` = '2016-10-19' AND edge_availability.`store_id` = 84) Y
ORDER BY id
You can use a LEFT JOIN to detect when a date isn't found in the e_availability table. The join will return NULL for all the columns in that table, then you can default to the value from e_sku.
SELECT d.date, s.id, IFNULL(a.is_available, s.is_available) AS is_available
FROM all_dates AS d
CROSS JOIN e_sku AS s
LEFT JOIN e_availability ON d.working_date = a.date AND s.id = a.e_sku_id
You need to create an additional table all_dates that contains all the dates that you want to report on. See What is the most straightforward way to pad empty dates in sql results (on either mysql or perl end)? for how you can create such a table dynamically.
Related
Hello there are two tables
Interval
id
is_full
1
1
2
0
3
0
entry_penalty
interval_id
entry_id
amount
2
14
55
3
14
7
3
14
1
1
15
4
1
15
8
2
15
11
So i am trying to display Sum of all entry_penalties per interval, twist is even if there is no relation between entry_penalty and interval table i should display full course interval sum per entry_id (related to is_full field).
For example total results should be in this case
interval_id
entry_id
amount
1
14
63
2
14
55
3
14
8
1
15
23
2
15
11
I have tried with sub query but it ignores to do calculation when there is no relation between entry_penalties and interval tables regarding is_full column.
My code so far.
SELECT
ep.interval_id,
IF (
i.is_full,
(
SELECT SUM(ep2.amount) * 1000 FROM entry_penalty as ep2
WHERE ep2.entry_id = ep.entry_id
),
SUM(ep.amount) * 1000
) as penalty_time,
ep.entry_id
FROM entry_penalty ep
INNER JOIN \`interval\` i ON i.id = ep.interval_id
WHERE ep.entry_id IN (:entryIds)
GROUP BY interval_id, entry_id`
I would propose to deal with the two cases (full, not full) separately, and then use union all to combine the two results:
SELECT i.id, ep.entry_id, SUM(ep.amount)
FROM `interval` i,
entry_penalty ep
WHERE i.is_full
GROUP BY i.id, ep.entry_id
UNION ALL
SELECT i.id, ep.entry_id, SUM(ep.amount)
FROM entry_penalty ep
INNER JOIN `interval` i
ON ep.interval_id = i.id
AND NOT i.is_full
GROUP BY i.id, ep.entry_id
ORDER BY 2, 1
See it run on dbfiddle.uk, where it outputs:
id
entry_id
SUM(ep.amount)
1
14
63
2
14
55
3
14
8
1
15
23
2
15
11
I have two tables to join in SQL using the ID column in both. Table 1 has only unique values of ID as follows and I want to keep all columns of this table:
ID code 1 code 2
1 123 99
2 222 09
3 344 13
Table 2 has multiple rows of each ID as follows:
ID application_time Application Number
1 11jan2004 123
2 15oct2010 124
1 24nov2008 845
3 05sep2010 166
1 07feb2001 865
2 24aug2017 545
3 12mar2009 233
2 11dec2001 811
So, from table 2, I want to add the total count of each ID, and Min and Max of Application_time to table 1. I also need to count the number Application Numbers that start with 8. of I do not know where I should use group by (). So the outcome should look like:
ID code 1 code 2 count Min (application_time) Max (application_time)
1 123 99 3 07feb2001 24nov2008
2 222 09 3 11dec2001 24aug2017
3 344 13 2 12mar2009 05sep2010
Count of Application Number starting with 8
2
1
0
here is how you can do it:
select
t1.Id
,t1.code1
,t1.code2
, count(*) count
,min(application_time)
,max(application_time)
, sum( case when left( t2.application number, 1 ) = '8' then 1 else 0 end )
from table1 t1
join table2 t2
on t1.Id = t2.Id
group by
t1.Id
,t1.code1
,t1.code2
I have 3 tables that I have joined in the MySQL query below. All works well EXCEPT I would like the timeadj value with a 1 in column countingtime
to show from table 'data', not the first timeadj value the query finds.
I know this needs to be a query within a query but I am going around in circles and getting no where.
SELECT ttt_entries.tttid, ttt_teams.teamname, data.RacersInTeam,
ttt_entries.CoffeeClass, SEC_TO_TIME(data.timeadj),
COUNT(IF(data.division=5,1,NULL)) 'A+',
COUNT(IF(data.division=10,1,NULL)) A,
COUNT(IF(data.division=20,1,NULL)) B,
COUNT(IF(data.division=30,1,NULL)) C,
COUNT(IF(data.division=40,1,NULL)) D
FROM ttt_entries
INNER JOIN ttt_teams
ON ttt_entries.tttid = ttt_teams.tttid
INNER JOIN (SELECT * FROM data ORDER BY data.countingtime DESC) as data
ON ttt_entries.tttid = data.teamid
WHERE ttt_entries.eventDate = DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE()) >4, -5, 2) + DAYOFWEEK(CURDATE())) * -1 DAY) -- last Thursday
AND data.wtrlid = '22'
GROUP BY ttt_teams.tttid
ORDER BY data.timeadj ASC
For example.... In Team 1 (data.teamid=1) there are 8 time values in timeadj. In the adjacent column (countingtime) is a value either 1 or 0 but only ever 1x 1 per team.
Table ttt_entries
ID tttid CoffeeClass
1 23 Mocha
2 52 Espresso
3 6 Frappe
Table ttt_teams
tttid Name
6 Team A
23 Team 1
52 Team 2
Table 'data'
id wtrlid teamid timeadj countingtime division
1 22 23 3467.123 0 10
2 22 23 3467.125 0 20
3 22 23 3467.432 0 10
4 22 23 3469.000 1 10
5 22 23 3469.112 0 10
6 22 23 3468.987 0 5
My code brings back
tttid teamname RacersInTeam CoffeeClass Time A+ A B C D
23 Team 1 6 Mocha 3467.123 1 4 1 0 0
I need it to bring back the same data but a different time:
tttid teamname RacersInTeam CoffeeClass Time A+ A B C D
23 Team 1 6 Mocha 3469.000 1 4 1 0 0
You can try below way -
SELECT ttt_entries.tttid, ttt_teams.teamname, data.RacersInTeam,
ttt_entries.CoffeeClass, SEC_TO_TIME(max(case when countingtime=1 then data.timeadj end)),
COUNT(IF(data.division=5,1,NULL)) 'A+',
COUNT(IF(data.division=10,1,NULL)) A,
COUNT(IF(data.division=20,1,NULL)) B,
COUNT(IF(data.division=30,1,NULL)) C,
COUNT(IF(data.division=40,1,NULL)) D
FROM ttt_entries
INNER JOIN ttt_teams
ON ttt_entries.tttid = ttt_teams.tttid
INNER JOIN (SELECT * FROM data ORDER BY data.countingtime DESC) as data
ON ttt_entries.tttid = data.teamid
WHERE ttt_entries.eventDate = DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE()) >4, -5, 2) + DAYOFWEEK(CURDATE())) * -1 DAY) -- last Thursday
AND data.wtrlid = '22'
GROUP BY ttt_teams.tttid
ORDER BY data.timeadj ASC
I need a column from row value.
I have two table.
Table 1 : working_day Contains list of all working day date.
date
--------
2013-03-30
2013-03-29
2013-03-28
Table 2 : entry contains each employee in and out time.
id In Out Date
1 9 0 2013-03-30
2 8 0 2013-03-30
3 7 0 2013-03-30
1 8 18 2013-03-29
2 9 16 2013-03-29
3 6 20 2013-03-29
4 12 15 2013-03-29
Expected Output :
ID 29-03-2013_IN 29-03-2013_Out 30-03-2013_In
1 8 18 9
2 9 16 8
3 6 20 7
4 12 15 0
Tried :
SELECT id,
Case condition1 for 29_in, // I don't know which condition suite here.
Case condition1 for 29_out,
Case condition1 for 30_in
FROM entry
WHERE DATE
IN (
SELECT *
FROM (
SELECT DATE
FROM working_day
ORDER BY DATE DESC
LIMIT 0 , 2
)a
)
You could try something like that:
select
e.id,
(SELECT `in` FROM entry WHERE id = e.id AND date = '2013-03-30') as '2013-03-30_in',
(SELECT `in` FROM entry WHERE id = e.id AND date = '2013-03-29') as '2013-03-29_in',
(SELECT `out` FROM entry WHERE id = e.id AND date = '2013-03-29') as '2013-03-29_out'
from entry e
group by e.id;
Here is Demo
IMO you should do this in application instead of SQL
I have a query that involves searching database over a range of 30 days. Queries, both with correct output and wrong output are below:
CORRECT RESULTS:
SELECT
affiliates.member_id,
IFNULL( COUNT(orders.deal_id) , 0 ) AS deals_count,
IFNULL( SUM(orders.quantity) , 0 ) AS deals_quanity
FROM affiliates
LEFT JOIN deals ON affiliates.member_id = deals.member_id
LEFT JOIN orders ON deals.deal_id = orders.deal_id
LEFT JOIN customers_orders_link ON orders.order_id = customers_orders_link.order_id
AND DATE(customers_orders_link.datetime) BETWEEN '2011-06-01' AND '2011-07-01'
AND customers_orders_link.order_status = 'Delivered'
GROUP BY affiliates.member_id;
EXPECTED & RECEIVED: (Correct)
MemberID COUNT SUM
1 11 16
2 0 0
WRONG RESULTS:
//Notice the change in the date range
SELECT
affiliates.member_id,
IFNULL( COUNT(orders.deal_id) , 0 ) AS deals_count,
IFNULL( SUM(orders.quantity) , 0 ) AS deals_quanity
FROM affiliates
LEFT JOIN deals ON affiliates.member_id = deals.member_id
LEFT JOIN orders ON deals.deal_id = orders.deal_id
LEFT JOIN customers_orders_link ON orders.order_id = customers_orders_link.order_id
AND DATE(customers_orders_link.datetime) BETWEEN '2011-10-01' AND '2011-10-31'
AND customers_orders_link.order_status = 'Delivered'
GROUP BY affiliates.member_id
EXPECTED:
MemberID COUNT SUM
1 0 0
2 0 0
BUT I RECEIVE: (INCORRECT OUTPUT)
MemberID COUNT SUM
1 11 16
2 0 0
The first query is producing correct results whereas the second query is producing incorrect results. Even if I use a date in the past as the range, I still receive the same Incorrect Output. Its as if the query is completely ignoring the date range specification. So this case of ignoring the date range specification seems to be the problem.
How can I make the query "see" and "obey" the date range specification and actually receive the Expected Output for the 2nd query listed above?
EDIT 1:
//Table: Orders
order_id deal_id quantity price
1 1 2 40.00
1 2 1 15.00
2 1 1 20.00
3 9 1 5.00
4 1 2 40.00
4 9 2 10.00
5 1 1 20.00
5 9 1 5.00
6 1 2 40.00
6 9 2 10.00
7 1 1 20.00
8 11 1 1.00
//Table: customers_orders_link
order_id customer_id order_status datetime
1 4 Cancelled 2011-06-05 20:26:45
2 4 Delivered 2011-06-05 20:38:28
3 4 Pending Payment 2011-06-05 20:56:50
4 4 Pending Payment 2011-06-09 17:03:08
5 4 Pending Payment 2011-06-09 17:12:23
6 4 Pending Payment 2011-06-09 17:19:57
7 4 Pending Payment 2011-06-09 17:40:59
8 4 Pending Payment 2011-06-10 03:55:17
I solved it myself using a totally different method.
I don't know what your data looks like, but I suspect your LEFT JOIN customers_orders_link is to blame. If you only want to tally COUNT() and SUM() when the conditions of that table are met, it should be a standard JOIN in place of a LEFT JOIN.