I have the code below but i want to arrange it by date_available desc and group it by store_id so that i will only return 1 value.
SELECT
product_to_store.store_id,
product.date_available,
product.product_id,
product_description.name,
product_to_category.category_id,
pcd3.name,
lvl2.parent_id,
pcd2.name,
CASE
WHEN lvl2.parent_id > 0 THEN lvl1.parent_id
ELSE 0
END,
pcd1.name,
product.quantity,
product_type.type
FROM product
inner join product_to_store on (product.product_id=product_to_store.product_id)
inner join product_description on (product.product_id = product_description.product_id)
inner join product_to_category on (product.product_id = product_to_category.product_id)
inner join product_type on (product.product_id = product_type.product_id)
inner join store on (product_to_store.store_id = store.store_id)
inner join product_category as lvl2 on (product_to_category.category_id = lvl2.category_id)
inner join product_category as lvl1 on (lvl1.category_id = lvl2.parent_id)
inner join product_category_description as pcd3 on (pcd3.category_id = lvl2.category_id)
inner join product_category_description as pcd2 on (pcd2.category_id = lvl2.parent_id)
inner join product_category_description as pcd1 on (pcd1.category_id = lvl1.parent_id)
Sample table:
store_id date_available name
1 2017-05-04 T1
1 0000-00-00 T2
2 2017-06-04 T3
3 0000-00-00 T4
2 2017-04-04 T5
3 0000-00-00 T6
Expected result:
store_id date_available name
1 2017-05-04 T1
2 2017-06-04 T3
3 0000-00-00 T4
How can i do that in mysql? Please help me thank you.
Use this as a hint:
-- Create some testing data
IF OBJECT_ID('tempdb..#product') IS NOT NULL DROP TABLE #product
CREATE TABLE #product(
[store_id] int
,[date_available] varchar(50)
,[name] varchar(50)
)
INSERT INTO #product VALUES
(1, '2017-05-04', 'T1')
,(1, '0000-00-00', 'T2')
,(2, '2017-06-04', 'T3')
,(3, '0000-00-00', 'T4')
,(2, '2017-04-04', 'T5')
,(3, '0000-00-00', 'T6')
-- Get result
SELECT p1.[store_id], p1.[date_available], MIN(p2.[name]) AS [name]
FROM (
SELECT [store_id], MAX([date_available]) AS [date_available] FROM #product
GROUP BY [store_id]
) p1
INNER JOIN #product p2
ON p1.[store_id] = p2.[store_id] AND p1.[date_available] = p2.[date_available]
GROUP BY p1.[store_id], p1.[date_available]
-- Destroy the temp table
DROP TABLE #product
Then in your long script, you may rewrite it to something like this:
SELECT product_to_store.store_id,
product.date_available,
product.product_id,
.
.
.
FROM product
INNER JOIN ...
INNER JOIN ...
INNER JOIN (
SELECT p1.[store_id], p1.[date_available], MIN(p2.[name]) AS [name]
FROM (
SELECT [store_id], MAX([date_available]) AS [date_available] FROM #product
GROUP BY [store_id]
) p1
INNER JOIN #product p2
ON p1.[store_id] = p2.[store_id] AND p1.[date_available] = p2.[date_available]
GROUP BY p1.[store_id], p1.[date_available]
) store ON (product_to_store.store_id = store.store_id)
INNER JOIN ...
INNER JOIN ...
Related
I have an issue with the following mySQL query where it fails when Max date is introduced as shown below.
I get the following error
Error Code: 1054. Unknown column 'order_items.ORDER_ITEM_ID' in 'where
clause'
SET #UserID = 160;
SET #OrderDateTime = '2018-11-13 09:23:45';
SELECT
order_items.ORDER_ID,
listing_region.LIST_REGION_REGION_ID,
listings.LISTING_ID,
order_items.ORDER_REQUIRED_DATE_TIME,
listings.LISTING_NICK_NAME,
order_items.ORDER_QUANTITY,
order_price.ORDER_PRICE_ID,
order_items.ORDER_PORTION_SIZE,
t.LATEST_DATE,
t.ORDER_STATUS
FROM order_status_change, order_items
INNER JOIN listings ON listings.LISTING_ID = order_items.ORDER_LISTING_ID
INNER JOIN listing_region ON listing_region.LIST_REGION_LISTING_ID = listings.LISTING_ID
INNER JOIN order_price ON order_price.ORDERP_ITEM_ID = order_items.ORDER_ITEM_ID
INNER JOIN
(
SELECT MAX(order_status_change.ORDER_STATUS_CHANGE_DATETIME) AS LATEST_DATE, order_status_change.ORDER_ITEM_ID, order_status_change.ORDER_STATUS
FROM order_status_change
WHERE order_status_change.ORDER_ITEM_ID = order_items.ORDER_ITEM_ID
) AS t ON order_status_change.ORDER_ITEM_ID = t.ORDER_ITEM_ID AND order_status_change.ORDER_STATUS_CHANGE_DATETIME = t.LATEST_DATE
WHERE ((order_items.ORDER_USER_ID = #UserID) AND DATE(order_items.ORDER_REQUIRED_DATE_TIME) = DATE(#OrderDateTime))
Any help ?
I have assumed you can join order_status_change on order_items.ID = order_status_change.ORDER_ITEM_ID
If that is valid then I think this will achieve what you are after:
SET #UserID = 160;
SET #OrderDateTime = '2018-11-13 09:23:45';
SELECT
order_items.ORDER_ID
, listing_region.LIST_REGION_REGION_ID
, listings.LISTING_ID
, order_items.ORDER_REQUIRED_DATE_TIME
, listings.LISTING_NICK_NAME
, order_items.ORDER_QUANTITY
, order_price.ORDER_PRICE_ID
, order_items.ORDER_PORTION_SIZE
, t.LATEST_DATE
, order_status_change.ORDER_STATUS
FROM order_items
INNER JOIN listings ON listings.LISTING_ID = order_items.ORDER_LISTING_ID
INNER JOIN listing_region ON listing_region.LIST_REGION_LISTING_ID = listings.LISTING_ID
INNER JOIN order_price ON order_price.ORDERP_ITEM_ID = order_items.ORDER_ITEM_ID
INNER JOIN order_status_change ON order_items.ID = order_status_change.ORDER_ITEM_ID
INNER JOIN (
SELECT
MAX( mc.ORDER_STATUS_CHANGE_DATETIME ) AS LATEST_DATE
, mc.ORDER_ITEM_ID
FROM order_status_change AS mc
GROUP BY
mc.ORDER_ITEM_ID
) AS t
ON order_status_change.ORDER_ITEM_ID = t.ORDER_ITEM_ID
AND order_status_change.ORDER_STATUS_CHANGE_DATETIME = t.LATEST_DATE
WHERE order_items.ORDER_USER_ID = #UserID
AND DATE( order_items.ORDER_REQUIRED_DATE_TIME ) = DATE( #OrderDateTime )
You need to avoid this in future:
FROM order_status_change , order_items
That comma between the 2 table names IS a join, but it is from an older syntax and it is LOWER in precedence than the other joins of your query. Also, by default this comma based join acts as an equivalent to a cross join which MULTIPLIES the number of rows. In brief, please do NOT USE commas between table names.
The other issue is that you were missing a group by clause and I believe you just want to get the "latest" date from this aggregation, once that is determined link back to that table to get the status relevant to that date. (i.e. you can't group by status in the subquery, otherwise you get the latest dateS (one for each status).
Here's a simplified version to illustrate the problem.
DROP TABLE IF exists t,t1;
create table t (id int);
create table t1(id int,dt date);
insert into t values (1),(2);
insert into t1 values (1,'2018-01-01'),(1,'2018-02-01'),(2,'2018-01-01');
select t.*,t2.maxdt
from t
join (select max(dt) maxdt,t1.id from t1 where t1.id = t.id) t2
on t2.id = t.id;
ERROR 1054 (42S22): Unknown column 't.id' in 'where clause'
You could group by in the sub query and then the on clause will come into play
select t.*,t2.maxdt
from t
join (select max(dt) maxdt,t1.id from t1 group by t1.id) t2
on t2.id = t.id;
+------+------------+
| id | maxdt |
+------+------------+
| 1 | 2018-02-01 |
| 2 | 2018-01-01 |
+------+------------+
2 rows in set (0.00 sec)
If you want an answer closer to your problem please add sample data and expected output to the question as text of to sqlfiddle.
I have two tables, 'team' and 'tickets'. Right now its displaying all records and also which ticket the team member is dispatched too.
I now need to count the number of tickets for each team.
http://sqlfiddle.com/#!9/609d4f/18
Here's my attempt:
SELECT
team.techid,
team.name,
tickets.techid,
tickets.customer,
tickets.callstatus,
tickets.serialnumber
FROM team
LEFT JOIN tickets
ON tickets.techid = team.techid AND (tickets.callstatus = 'Dispatch') AND
(COUNT(tickets.customer) WHERE tickets.techid = team.techid )
Update
Working example but only missing the count column:
http://sqlfiddle.com/#!9/609d4f/19
Update2
Tim, thank you for your help but your example doesn't work.
The table should look like this, minus the missing columns of course:
|---------------------|------------------|
| Tech ID | Count |
|---------------------|------------------|
| Tech1 | 1 |
|---------------------|------------------|
| Tech2 | 1 |
|---------------------|------------------|
| Tech3 | 0 |
|---------------------|------------------|
http://sqlfiddle.com/#!9/bfcdf5/1
As you see below, tech1 and tech2 both have records in ato_openservicecalls where the SC_CallStatus is Dispatch
insert into `serviceteam` VALUES (1, 'tech1', 'name1', 'manager1', 'dispatcher1', 'cellphone1');
insert into `serviceteam` VALUES (2, 'tech2', 'name2', 'manager2', 'dispatcher2', 'cellphone2');
insert into `serviceteam` VALUES (3, 'tech3', 'name3', 'manager3', 'dispatcher3', 'cellphone3');
insert into `ato_openservicecalls` VALUES (1, 'tech1', 'Dispatch', 'customer1', 'age1', 'timestamp1', 'serial1', 'comment1');
insert into `ato_openservicecalls` VALUES (2, 'tech2', 'Dispatch', 'customer2', 'age2', 'timestamp2', 'serial2', 'comment2');
insert into `ato_openservicecalls` VALUES (3, 'tech3', 'callstatus3', 'customer3', 'age3', 'timestamp3', 'serial3', 'comment3');
SELECT
t1.techid,
t1.techname,
t1.manager,
t1.dispatcher,
t1.cellphone,
t2.SC_SCTechID,
t2.BCARNA,
t2.SC_CallStatus,
t2.Serial_ID,
t2.Age,
t2.SC_CallTimestamp,
t2.SC_CallComment,
COALESCE(t3.num_tickets, 0) AS num_tickets
FROM serviceteam t1
LEFT JOIN ato_openservicecalls t2
ON t1.techid = t2.SC_SCTechID AND t2.SC_CallStatus = 'Dispatch'
LEFT JOIN
(
SELECT t1.techid, COUNT(*) AS num_tickets
FROM serviceteam t1
INNER JOIN ato_openservicecalls t2
ON t1.techid = t2.SC_SCTechID
WHERE t2.SC_CallStatus = 'Dispatch'
) t3
ON t1.techid = t3.techid;
In MySQL versions earlier than 8+, we can find the counts using a subquery and then join to it:
SELECT
t1.techid,
t1.name,
t2.techid,
t2.customer,
t2.callstatus,
t2.serialnumber,
COALESCE(t3.num_tickets, 0) AS num_tickets
FROM team t1
LEFT JOIN tickets t2
ON t1.techid = t2.techid AND t2.callstatus = 'Dispatch'
LEFT JOIN
(
SELECT t1.techid, COUNT(*) AS num_tickets
FROM team t1
INNER JOIN tickets t2
ON t1.techid = t2.techid
WHERE t2.callstatus = 'Dispatch'
) t3
ON t1.techid = t3.techid;
With MySQL 8+ or later, we can take advantage of analytic functions:
SELECT
t1.techid,
t1.name,
t2.techid,
t2.customer,
t2.callstatus,
t2.serialnumber,
COUNT(t2.customer) OVER (PARTITION BY t1.techid) num_tickets
FROM team t1
LEFT JOIN tickets t2
ON t1.techid = t2.techid AND t2.callstatus = 'Dispatch';
Edit:
You completely changed your question, invalidating my first accepted answer. Here is the new query:
SELECT
t1.techid,
COUNT(t2.customer) AS num_tickets
FROM team t1
LEFT JOIN tickets t2
ON t1.techid = t2.techid AND t2.callstatus = 'Dispatch'
GROUP BY
t1.techid;
I have the following 4 tables:
student_info:
S_ID naam email telefoon locatie U_ID
1 Walter Walter# 03938 Home 1
student_combi:
S_ID V_ID
1 1
student_vak:
V_ID vak R_ID
1 HTML 1
student_richting:
R_ID richting
1 Web-Development
I would like the query to SELECT 'vak' (from the 'student_vak' table) and 'richting' (from the 'student_richting' table) using INNER JOIN
So far I have this:
SELECT student_vak.vak,student_richting.richting
FROM student_vak
INNER JOIN student_richting ON student_vak.R_ID = student_richting.R_ID
INNER JOIN student_combi ON student_info.S_ID = student_combi.S_ID
INNER JOIN student_vak ON student_combi.V_ID = student_vak.V_ID
INNER JOIN student_richting ON student_vak.R_ID = student_richting.R_ID
Thank you in advance if you know the answer.
This following will fulfil your need.
SELECT S.S_Id Student_Id, S.Naam Student_Name, SV.vak, SR.richting
FROM Student_Info S
INNER JOIN Student_Combi SC ON S.S_id = SC.S_Id
INNER JOIN Student_Vak SV ON SC.V_Id = SV.V_Id
INNER JOIN student_richting SR ON SV.R_Id = SR.R_Id
--Example
CREATE TABLE #student_vak
(V_ID INT,
vak NVARCHAR(256),
R_ID INT)
INSERT INTO #student_vak
SELECT '1', 'HTML','1'
CREATE TABLE #student_richting
(R_ID INT,
richting NVARCHAR(256)
)
INSERT INTO #student_richting
SELECT '1', 'Web-Development'
SELECT SV.vak, SR.richting
FROM #student_vak SV
INNER JOIN #student_richting SR ON SV.R_Id = SR.R_Id
Say I have a database similar to the following:
Table events_degree:
event_id degree_id
1 1
1 31
... ...
Table events_area:
event_id area_id
1 1
1 31
... ...
Table events_schedule:
event_id schedule
1 Time 1
1 Time 2
... ...
Table events:
id name
1 prom
2 homecoming
... ...
Table degree:
id name shortened
1 computer science cs
2 something else se
... ... ...
Table area:
id name
1 hall 1
2 gym
... ...
Table building:
id name
1 main building
2 second building
... ...
What i want to do it's merge the columns since i have this query
SELECT `e`.*, `eh`.`start_date`, `eh`.`end_date`, `c`.`name` AS `degree_name`, `c`.`shortened` AS `shortened_degree`, `ai`.`name` AS `area_name`, `ed`.`name` AS `building_name`
FROM `events` `e`
LEFT JOIN `event_schedule` `eh` ON `e`.`id` = `eh`.`event_id`
LEFT JOIN `event_degree` `ec` ON `e`.`id` = `ec`.`event_id`
LEFT JOIN `degree` `c` ON `c`.`id` = `ec`.`degree_id`
LEFT JOIN `event_area` `ea` ON `e`.`id` = `ea`.`event_id`
LEFT JOIN `area` `ai` ON `ai`.`id` = `ea`.`area_id`
LEFT JOIN `building` `ed` ON `ed`.`id` = `ai`.`building_id`
WHERE `e`.`active` = '1'
AND `eh`.`start_date` >= '2016-03-08'
AND `eh`.`end_date` < '2016-07-01'
ORDER BY `eh`.`fecha_inicio` ASC;
and as a result i get all the rows "duplicated" as you can see in the picture
how can i avoid this, thanks for your help
** note **
it's the same event so it should be displaying only 1 row for every event the problem is that i has 3 many to many relationships
so the things that change are only dates, degrees and areas
You can use GROUP BY
SELECT DISTINCT `e`.*, `eh`.`start_date`, `eh`.`end_date`, `c`.`name` AS `degree_name`, `c`.`shortened` AS `shortened_degree`, `ai`.`name` AS `area_name`, `ed`.`name` AS `building_name`
FROM `events` `e`
LEFT JOIN `event_schedule` `eh` ON `e`.`id` = `eh`.`event_id`
LEFT JOIN `event_degree` `ec` ON `e`.`id` = `ec`.`event_id`
LEFT JOIN `degree` `c` ON `c`.`id` = `ec`.`degree_id`
LEFT JOIN `event_area` `ea` ON `e`.`id` = `ea`.`event_id`
LEFT JOIN `area` `ai` ON `ai`.`id` = `ea`.`area_id`
LEFT JOIN `building` `ed` ON `ed`.`id` = `ai`.`building_id`
WHERE `e`.`active` = '1'
AND `eh`.`start_date` >= '2016-03-08'
AND `eh`.`end_date` < '2016-07-01'
GROUP BY `your_id`;
Use DISTINCT while selecting
SELECT DISTINCT `e`.*, `eh`.`start_date`, `eh`.`end_date`, `c`.`name` AS `degree_name`, `c`.`shortened` AS `shortened_degree`, `ai`.`name` AS `area_name`, `ed`.`name` AS `building_name`
FROM `events` `e`
LEFT JOIN `event_schedule` `eh` ON `e`.`id` = `eh`.`event_id`
LEFT JOIN `event_degree` `ec` ON `e`.`id` = `ec`.`event_id`
LEFT JOIN `degree` `c` ON `c`.`id` = `ec`.`degree_id`
LEFT JOIN `event_area` `ea` ON `e`.`id` = `ea`.`event_id`
LEFT JOIN `area` `ai` ON `ai`.`id` = `ea`.`area_id`
LEFT JOIN `building` `ed` ON `ed`.`id` = `ai`.`building_id`
WHERE `e`.`active` = '1'
AND `eh`.`start_date` >= '2016-03-08'
AND `eh`.`end_date` < '2016-07-01'
ORDER BY `eh`.`fecha_inicio` ASC;
Hi I want to filter logs using MySQL with a list of trackings.
Every log belongs to a server,
Every tracking belongs to a server and have 0..N patterns
Every pattern belongs to a tracking
I have 3 tables :
logs : | id | ip | url | server_id | ...
tracking : | id | server_id | name | other fields...
pattern : | id | tracking_id | pattern |
I want to count logs that match tracking for a specific server my problem is that my query mix up tracking that have pattern and those that don't.
SQL Fiddle : http://sqlfiddle.com/#!2/f11b1/2
SELECT COUNT(DISTINCT logs.ip), tr.name
FROM `logs`
INNER JOIN `trackings` as tr ON
( tr.server_id = logs.server_id )
AND -- OTHER conditions between log and tracking
LEFT JOIN `patterns` as pt ON
( pt.tracking_id = tr.id )
AND (logs.url LIKE pt.pattern )
GROUP BY tr.id
My problem is on the second join, if I use INNER JOIN patterns as pt ON I get correct results but only on trackings that have some patterns,
If I use LEFT JOIN patterns as pt ON I get all tracking but with a false count (I get the result of SELECT COUNT(DISTINCT logs.ip) FROM logs )
EDIT
I Can get the correct result with a field in tracking that indicates if the tracking has patterns and a UNION :
(
SELECT COUNT(DISTINCT lg.ip), tr.name
FROM `logs` as lg
INNER JOIN `trackings` as tr ON
( tr.server_id = lg.server_id )
AND (tr.hasPatterns = 1)
AND -- Other conditions
INNER JOIN `patterns` as pt ON
( pt.tracking_id = tr.id )
AND (lg.url LIKE pt.pattern )
WHERE
GROUP BY tr.id
)
UNION
(
SELECT COUNT(DISTINCT lg.ip), tr.name
FROM `logs` as lg
INNER JOIN `trackings` as tr ON
( tr.server_id = lg.server_id )
AND (tr.hasPatterns = 0)
WHERE
GROUP BY tr.id, lg.date
)
But I guess there is a way to do that without using Union...
You can put a conditional inside count, so I think the following does what you want:
SELECT COUNT(DISTINCT (case when tr.hasPatterns = 1 and pt.tracking_id is not null
then lg.ip
when tr.hasPatterns = 0
then lg.ip
end)), tr.name
FROM `logs` as lg
INNER JOIN `trackings` as tr ON
( tr.server_id = lg.server_id )
AND -- Other conditions
LEFT JOIN `patterns` as pt ON
( pt.tracking_id = tr.id )
AND (lg.url LIKE pt.pattern )
WHERE
GROUP BY tr.id
EDIT:
This is returning what you want:
SELECT COUNT(DISTINCT (case when tr.size = 0 and pt.tracking_id is not null
then lg.ip
when tr.size > 0 and lg.size > tr.size
then lg.ip
end)), tr.name
FROM `logs` as lg
INNER JOIN `trackings` as tr ON
( tr.server_id = lg.server_id )
LEFT JOIN `patterns` as pt ON
( pt.tracking_id = tr.id )
AND (lg.url LIKE pt.pattern )
GROUP BY tr.id;
Your SQL Fiddle has the additional condition lg.size > tr.size which is not in the original question.