I have following query
SELECT YEAR(T.date), MONTH(T.date), T.production, T.lineID, SUM(rework + scrap)
FROM
(SELECT MAX(positionID), date, production, lineID
FROM productionPerPosition
WHERE lineID = 2
AND date BETWEEN '2017-01-01' AND '2017-01-31'
GROUP BY date) AS T
INNER JOIN linePosition lp ON lp.lineID = T.lineID
INNER JOIN fttErrorType fet ON fet.positionID = lp.positionID
INNER JOIN fttData fd ON fd.errorID = fet.errorID
AND fd.date = T.date
GROUP BY YEAR(T.date), MONTH(T.date)
which gives this result
Now, I would like to group these results by year and month to get sum of production and sum of last column. I've tried this query
SELECT YEAR(T.date), MONTH(T.date), SUM(T.production), T.lineID, SUM(rework + scrap)
FROM
(SELECT MAX(positionID), date, production, lineID
FROM productionPerPosition
WHERE lineID = 2
AND date BETWEEN '2017-01-01' AND '2017-01-31'
GROUP BY date) AS T
INNER JOIN linePosition lp ON lp.lineID = T.lineID
INNER JOIN fttErrorType fet ON fet.positionID = lp.positionID
INNER JOIN fttData fd ON fd.errorID = fet.errorID
AND fd.date = T.date
GROUP BY YEAR(T.date), MONTH(T.date)
Which gives me
Here production sum is wrong! It seems that GROUP BY from 7th line in first query is ignored.
Any idea how could I get needed result?
Edit: In inner SELECT I have separate production for several different positions (positionID) but I'm using only production from position that has highest positionID
Group has missing grouping columns that why it is resulting in some unexpected result
SELECT YEAR(T.date), MONTH(T.date), SUM(T.production), T.lineID, SUM(rework + scrap)
FROM
(SELECT MAX(positionID), date, production, lineID
FROM productionPerPosition
WHERE lineID = 2
AND date BETWEEN '2017-01-01' AND '2017-01-31'
GROUP BY date, production, lineID) AS T
INNER JOIN linePosition lp ON lp.lineID = T.lineID
INNER JOIN fttErrorType fet ON fet.positionID = lp.positionID
INNER JOIN fttData fd ON fd.errorID = fet.errorID
AND fd.date = T.date
GROUP BY YEAR(T.date), MONTH(T.date), T.lineID
Has explained in e4c5 comment, you have to add all the unaggregated fields to your GROUP BY. I made it in the inner SELECT and in the main SELECT:
SELECT YEAR(T.date), MONTH(T.date), SUM(T.production), T.lineID, SUM(rework + scrap)
FROM
(SELECT MAX(positionID), date, production, lineID
FROM productionPerPosition
WHERE lineID = 2
AND date BETWEEN '2017-01-01' AND '2017-01-31'
GROUP BY date, production, lineID) AS T
INNER JOIN linePosition lp ON lp.lineID = T.lineID
INNER JOIN fttErrorType fet ON fet.positionID = lp.positionID
INNER JOIN fttData fd ON fd.errorID = fet.errorID
AND fd.date = T.date
GROUP BY YEAR(T.date), MONTH(T.date), T.lineID
Related
I have multiple tables that I am having to join together in order to work out how long tickets have been open, I am using the following query (convoluted I know!):
SELECT DISTINCT u_db.environments.name AS Env_name, TIMEDIFF(u_db.tickets.close_date, u_db.tickets.created_date) AS Total_open_time
FROM u_db.tickets
INNER JOIN u_db.ticket_units
ON u_db.tickets.id = u_db.ticket_units.ticket_id
INNER JOIN u_db.units
ON u_db.ticket_units.unit_id = u_db.units.id
INNER JOIN u_db.locations
ON u_db.units.location_id = u_db.locations.id
INNER JOIN u_db.location_groups
ON u_db.locations.locations_group_id = u_db.location_groups.id
INNER JOIN u_db.environments
ON u_db.location_groups.environment = u_db.environments.id
WHERE u_db.tickets.created_date >= '2021-09-01 00:00:00'
AND u_db.tickets.created_date < '2021-10-01 00:00:00'
AND u_db.location_groups.id IN (50,17,46,45,48,49)
AND u_db.tickets.id IN (132357,132361,132372,132473);
Note: the close_date and created_date are stored as TIMESTAMP.
This generates the following output:
Env_name Total_open_time
GA 27:38:59
GA 01:43:51
GR 04:32:58
GR 49:39:19
However, I would like to group by Env_name and SUM the Total_open_times for each group, so my desired output is:
Env_name Total_open_time
GA 29:22:50
GR 54:12:17
I cannot seem to get the times to totals to sum when I group by Env_name, any suggestions on how to achieve this would be greatly appreciated!
Guess you can sum with difference in seconds, then convert seconds to time
SELECT u_db.environments.name AS Env_name, SEC_TO_TIME(SUM(TIMESTAMPDIFF(SECOND, u_db.tickets.created_date, u_db.tickets.close_date))) AS Total_open_time
FROM u_db.tickets
INNER JOIN u_db.ticket_units
ON u_db.tickets.id = u_db.ticket_units.ticket_id
INNER JOIN u_db.units
ON u_db.ticket_units.unit_id = u_db.units.id
INNER JOIN u_db.locations
ON u_db.units.location_id = u_db.locations.id
INNER JOIN u_db.location_groups
ON u_db.locations.locations_group_id = u_db.location_groups.id
INNER JOIN u_db.environments
ON u_db.location_groups.environment = u_db.environments.id
WHERE u_db.tickets.created_date >= '2021-09-01 00:00:00'
AND u_db.tickets.created_date < '2021-10-01 00:00:00'
AND u_db.location_groups.id IN (50,17,46,45,48,49)
AND u_db.tickets.id IN (132357,132361,132372,132473)
GROUP BY Env_name
first time on here, hoping for help. (MySQL) I tried to use subqueries in a SELECT statement but when I GROUP BY, the single aggregate value outputs of the subqueries just produce the one same value for all rows in the table. This implies they are not GROUPED, right? How close am I to getting this right? Thanks
SELECT
c.name, ca.name, DATE_FORMAT(sp.created,'%Y%m') AS yr_month,
ss.signup_source, count(sp.seller_profile_id) AS No_seller_profiles,
(SELECT SUM(seller_invoice.gbp_value)/100
FROM seller_invoice JOIN seller_profile
ON seller_invoice.seller_profile_id = seller_profile.seller_profile_id
WHERE seller_invoice.created BETWEEN seller_profile.created AND ADDDATE(seller_profile.created, INTERVAL 30 DAY)),
(SELECT count(project_response.project_response_id)
FROM project_response JOIN seller_profile
ON project_response.seller_profile_id = seller_profile.seller_profile_id
WHERE project_response.created BETWEEN seller_profile.created AND ADDDATE(seller_profile.created, INTERVAL 30 DAY) AND project_response.is_visible_to_seller = 1)
FROM seller_profile AS sp
JOIN country AS c ON sp.country_id = c.country_id
JOIN seller_category AS sc ON sp.seller_profile_id = sc.seller_profile_id
JOIN category AS ca ON sc.category_id = ca.category_id
JOIN seller_signup_source AS ss ON sp.seller_profile_id = ss.seller_profile_id
WHERE sp.created BETWEEN '2018-11-01' AND '2018-12-31'
GROUP BY 1,2,3,4;
How can I create a query that will return the latest Soa LoanableAmount based on the LoanApplicationDate.
Ex:
For LoanID = 1, I want to get the Soa record with SoaID = 2 since this is the latest loanable amount for this LoanApplicationDate - 2017-07-01.
So far this is what I have accomplished:
select *
from Loan L
join Soa S
ON S.EmployeeID = L.EmployeeID
where S.TransactionDate <= L.LoanApplicationDate
To illustrate what I want to accomplish, please see screenshot below.
https://www.db-fiddle.com/f/3PBossUJLYQTQZJfZymiph/0
I think you want a join and then to filter to get the most recent date:
select l.*, s.*
from Loan l join
Soa s
on s.employeeid = l.employeeid
where s.TransactionDate <= (select max(s2.TransactionDate)
from Soa s2
where s2.employeeid = l.employeeid and
s2.TransactionDate <= l.LoanApplicationDate
);
I think you need to set the condition on the join:
select
L.LoanID,
L.EmployeeID,
L.LoanAmount,
L.LoanApplicationDate,
S.LoanableAmount,
S.TransactionDate
from Loan L join Soa S
ON S.EmployeeID = L.EmployeeID and
S.TransactionDate = (select max(TransactionDate) from Soa where TransactionDate <= L.LoanApplicationDate)
See the demo
SQL DEMO
select *
from Loan L
join Soa S
ON S.EmployeeID = L.EmployeeID
and S.TransactionDate =
(select max(S2.TransactionDate)
from Soa S2
where S2.TransactionDate <= L.LoanApplicationDate
and S2.`EmployeeID` = L.`EmployeeID`
)
The below query will give you all employee ids with loanable amount withdrawn on latest date
Select employee_id,
LoanableAmount
transactionDate from table
having
transactionDate=max(transactionDate)
group by employee_id
You need to run a subquery for each row:
select q.*, S.LoanableAmount, S.TransactionDate from
(select
L.*
,(select SoaID from Soa x where x.EmployeeID = L.EmployeeID and x.TransactionDate <= L.LoanApplicationDate order by TransactionDate DESC limit 1) as SoaID
from Loan L) q
join Soa S on S.SoaID = q.SoaID
Line 4 will give you the SoaID of the row in the Soa table that has the newest date that is less than or equal to the Application Date, then with that ID you just join and show the rest of the fields.
the following is the situation. I need to connect an order-table with a message-table. But i'm only interested in the first message(lowest message-id). The connection between the tables is the orderid.
$result = $this->db->executeS('
SELECT o.*, c.iso_code AS currency, s.name AS shippingMethod, m.message AS note
FROM '._DB_PREFIX_.'orders o
LEFT JOIN '._DB_PREFIX_.'currency c ON c.id_currency = o.id_currency
LEFT JOIN '._DB_PREFIX_.'message m ON m.id_order = o.id_order
LEFT JOIN '._DB_PREFIX_.'carrier s ON s.id_carrier = o.id_carrier
LEFT JOIN jtl_connector_link l ON o.id_order = l.endpointId AND l.type = 4
WHERE l.hostId IS NULL AND o.date_add BETWEEN DATE_SUB(NOW(), INTERVAL 1 WEEK) AND NOW()
GROUP BY o.id_order
HAVING MIN(m.id_message)
LIMIT '.$limit
);
This query works so far. But now orders without a message are missing.
Thank you for your help!
Markus
You want to select several orders and per order the first message. This is generally difficult in MySQL for the lack of window functions (e.g. ROW_NUMBER OVER). But as it's just one column from the message table you are interested in, you can use a subquery in the SELECT clause.
SELECT
o.*,
c.iso_code AS currency,
s.name AS shippingMethod,
(
SELECT m.message
FROM message m
WHERE m.id_order = o.id_order
ORDER BY m.id_message
LIMIT 1
) AS note
FROM orders o
JOIN currency c ON c.id_currency = o.id_currency
JOIN carrier s ON s.id_carrier = o.id_carrier
WHERE o.date_add BETWEEN DATE_SUB(NOW(), INTERVAL 1 WEEK) AND NOW()
AND NOT EXISTS
(
SELECT *
FROM jtl_connector_link l
WHERE l.endpointId = o.id_order
AND l.type = 4
);
I have the folowing sql query:
SELECT DISTINCT(tbl_products.product_id), tbl_products.product_title,
tbl_brands.brand_name, tbl_reviews.review_date_added,
NOW() AS time_now
FROM tbl_products, tbl_reviews, tbl_brands
WHERE tbl_products.product_id = tbl_reviews.product_id AND
tbl_products.brand_id = tbl_brands.brand_id
ORDER BY tbl_reviews.review_date_added DESC
That needs to filter out any duplicate product_id's unfortunatly selecting tbl_reviews.review_date_added makes each record unique which means DISTINCT will not work anymore.
Is there any otherway of doing this query so that product_id is still unique?
I did do the GROUP BY and the problem is I display the tbl_reviews.review_date_added on a website and it selects the oldest date. I need the newest date.
Regards
With the description given, it's a bit hard to be certain, but if review_date_added is the only problem, it seems like you want the MAX() of that date?
If the following doesn't help, please could you give example data, example output, and a description of how you want the output to be created?
SELECT
tbl_products.product_id,
tbl_products.product_title,
tbl_brands.brand_name,
MAX(tbl_reviews.review_date_added) AS review_date_added,
NOW() AS time_now
FROM
tbl_products
INNER JOIN
tbl_reviews
ON tbl_products.product_id = tbl_reviews.product_id
INNER JOIN
tbl_brands
ON tbl_products.brand_id = tbl_brands.brand_id
GROUP BY
tbl_products.product_id,
tbl_products.product_title,
tbl_brands.brand_name
ORDER BY
MAX(tbl_reviews.review_date_added) DESC
Distinct works for the entire row. The parenthesis are just around the field:
distinct (a), b, c === distinct a, b, c
A straightforward solution is group by. You can use min to select the oldest date.
select tbl_products.product_id
, min(tbl_products.product_title)
, min(tbl_brands.brand_name)
, min(tbl_reviews.review_date_added)
, NOW() AS time_now
FROM tbl_products, tbl_reviews, tbl_brands
WHERE tbl_products.product_id = tbl_reviews.product_id AND
tbl_products.brand_id = tbl_brands.brand_id
GROUP BY
tbl_products.product_id
ORDER BY
min(tbl_reviews.review_date_added) DESC
Note that if a product can have multiple brands, this will pick the lowest one.
Try this:
SELECT pr.product_id, pr.product_title,
bd.brand_name,
(SELECT MAX(rev.review_date_added) FROM tbl_reviews rev
WHERE pr.product_id = rev.product_id) AS maxdate,
NOW() AS time_now
FROM tbl_products pr INNER JOIN tbl_reviews re
ON pr.product_id = re.product_id
INNER JOIN tbl_brands bd
ON pr.brand_id = bd.brand_id
GROUP BY pr.product_id
ORDER BY re.review_date_added DESC
or (as suggested by #Hogan)
SELECT pr.product_id, pr.product_title,
bd.brand_name, md.maxdate
NOW() AS time_now
FROM tbl_products pr INNER JOIN tbl_reviews re
ON pr.product_id = re.product_id
INNER JOIN tbl_brands bd
ON pr.brand_id = bd.brand_id
INNER JOIN (SELECT product_id, MAX(review_date_added) AS maxdate
FROM tbl_reviews rev GROUP BY product_id) md
ON pr.product_id = md.product_id
GROUP BY pr.product_id
ORDER BY re.review_date_added DESC
I combined the answer of Andomar with some changes you will find here.
SELECT tbl_products.product_id, tbl_products.product_title,
tbl_products.product_date_added, tbl_brands.brand_name,
MAX(tbl_reviews.review_date_added) AS review_date_added, NOW() AS time_now
FROM tbl_products, tbl_reviews, tbl_brands
WHERE tbl_products.product_id = tbl_reviews.product_id AND
tbl_products.brand_id = tbl_brands.brand_id
GROUP BY tbl_products.product_id
ORDER BY MAX(tbl_reviews.review_date_added) DESC
Works beautifully and shows the newest date at tbl_reviews.review_date_added.
Regards