I am a little confused by this strange MySQL behaviour. I am receiving the dreaded Every derived table must have its own alias error.
Usually, I can circumvent this by adding an AS clause to the primary SELECT statement, however it does not see to work with the following example:
SELECT SUM (`a`.`total`) AS `total` FROM (
SELECT COUNT(DISTINCT(`item_sales`.`id`)) AS `total`,
(SELECT COUNT(DISTINCT(`sale_item`)) AS `offers` FROM `item_sales_bids` WHERE `user_id` = 2) AS `offers`
FROM `item_sales`
INNER JOIN `item_sales_bids` ON `item_sales`.`id` = `item_sales_bids`.`sale_item`
WHERE `item_sales`.`buyer` != 2
AND `item_sales`.`sold` = 1
GROUP BY `item_sales`.`id`
HAVING `offers` > 0
) UNION (
SELECT COUNT(*) AS `total`,
`item_sales`.`reserve`,
(SELECT COUNT(*) FROM `item_sales_bids` WHERE `user_id` = 2) AS `bids`,
(SELECT MAX(`max_bid`) AS `max` FROM `item_sales_bids` WHERE `user_id` = 2) AS `maxBid`,
SUM((`item_sales`.`list_date` + (`item_sales`.duration * 86400)) - UNIX_TIMESTAMP()) AS `endTime`
FROM `item_sales`
INNER JOIN `item_sales_bids` ON `item_sales_bids`.`sale_item` = `item_sales`.`id`
GROUP BY `item_sales`.`id`
HAVING `endTime` < 0
AND `maxBid` < `item_sales`.`reserve`
)
) `a`
Can anyone point out what I am missing? Please note that adding an alias to the joins results in the same error.
You should put an UNION keyword inside the subquery as below
SELECT SUM (`a`.`total`) AS `total`
FROM (
SELECT COUNT(DISTINCT(`item_sales`.`id`)) AS `total`,
(SELECT COUNT(DISTINCT(`sale_item`)) AS `offers` FROM `item_sales_bids` WHERE `user_id` = 2) AS `offers`
FROM `item_sales`
INNER JOIN `item_sales_bids` ON `item_sales`.`id` = `item_sales_bids`.`sale_item`
WHERE `item_sales`.`buyer` != 2
AND `item_sales`.`sold` = 1
GROUP BY `item_sales`.`id`
HAVING `offers` > 0
UNION
SELECT COUNT(*) AS `total`,
`item_sales`.`reserve`,
(SELECT COUNT(*) FROM `item_sales_bids` WHERE `user_id` = 2) AS `bids`,
(SELECT MAX(`max_bid`) AS `max` FROM `item_sales_bids` WHERE `user_id` = 2) AS `maxBid`,
SUM((`item_sales`.`list_date` + (`item_sales`.duration * 86400)) - UNIX_TIMESTAMP()) AS `endTime`
FROM `item_sales`
INNER JOIN `item_sales_bids` ON `item_sales_bids`.`sale_item` = `item_sales`.`id`
GROUP BY `item_sales`.`id`
HAVING `endTime` < 0
AND `maxBid` < `item_sales`.`reserve`
) `a`
you can include UNION inside the subquery,
SELECT SUM (`a`.`total`) AS `total`
FROM
(
--- your first query
UNION
--- your second query
) a
Related
I've been trying to figure this one out for days but can't come up with a solution.
Here are the table schemes.
This is my current query.
SELECT DISTINCT `address`, `order`.`id`
FROM `order`, `ordered_articles`
WHERE `order`.`id` = `f_order_id`
AND `Status` > 1
AND `Status` <4;
The problem is that the query returns as long as there is one article with status bigger than 1. I need a query where all the articles of that order have a status bigger than 1.
You can do it with NOT EXISTS:
SELECT o.`address`, o.`id`
FROM `order` o
WHERE NOT EXISTS (
SELECT 1 FROM `ordered_articles`
WHERE `f_order_id` = o.`id`
AND (`Status` <= 1 OR `Status` >= 4 )
);
or:
SELECT o.`address`, o.`id`
FROM `order` o INNER JOIN `ordered_articles` i
ON i.`f_order_id` = o.`id`
GROUP BY o.`address`, o.`id`
HAVING SUM(`Status` <= 1 OR `Status` >= 4) = 0;
I am having the following query to fetch the data from the table.
SELECT rental_plans.*,
( ( inventory.total_inventory
+ vehicles.tmp_qty ) - Ifnull(reservation.total_reserved, 0) ) AS
vehicle_inventory
FROM `rental_plans`
INNER JOIN `vehicles`
ON `vehicles`.`id` = `rental_plans`.`vehicle_id`
LEFT JOIN (SELECT Count(*) AS total_inventory,
vehicle_id
FROM vehicle_inventories
GROUP BY vehicle_id) AS inventory
ON `inventory`.`vehicle_id` = `vehicles`.`id`
LEFT JOIN (SELECT vehicle_id,
Sum(qty) AS total_reserved
FROM `reservations`
WHERE ( '2018-12-18' BETWEEN pickup_date AND drop_date )
OR ( '2018-12-28' BETWEEN pickup_date AND drop_date )
AND `status` NOT IN ( 'RETURNED' )
GROUP BY `vehicle_id`) AS `reservation`
ON `rental_plans`.`vehicle_id` = `reservation`.`vehicle_id`
WHERE `rental_plans`.`id` > 0
AND `rental_plans`.`pickup` = '1'
AND `rental_plans`.`drop` = '10'
ORDER BY `rental_plans`.`price` ASC
But I want to handle where condition based on vehicle_inventory.
I tried with ... AND vehicle_inventory > 16 order by `rental_plans`.`price` ASC but this generates the error that column not found in the table
The reason is that vehicle_inventory is an alias and it is resolved after WHERE clause. You can read about that here. You can do something like:
SELECT *
FROM (SELECT rental_plans.*,
( ( inventory.total_inventory
+ vehicles.tmp_qty ) - Ifnull(reservation.total_reserved, 0)
) AS
vehicle_inventory
FROM `rental_plans`
INNER JOIN `vehicles`
ON `vehicles`.`id` = `rental_plans`.`vehicle_id`
LEFT JOIN (SELECT Count(*) AS total_inventory,
vehicle_id
FROM vehicle_inventories
GROUP BY vehicle_id) AS inventory
ON `inventory`.`vehicle_id` = `vehicles`.`id`
LEFT JOIN (SELECT vehicle_id,
Sum(qty) AS total_reserved
FROM `reservations`
WHERE ( '2018-12-18' BETWEEN
pickup_date AND drop_date )
OR ( '2018-12-28' BETWEEN
pickup_date AND drop_date )
AND `status` NOT IN ( 'RETURNED' )
GROUP BY `vehicle_id`) AS `reservation`
ON `rental_plans`.`vehicle_id` =
`reservation`.`vehicle_id`
WHERE `rental_plans`.`id` > 0
AND `rental_plans`.`pickup` = '1'
AND `rental_plans`.`drop` = '10')a
WHERE a.rental_plans > 16
ORDER BY `price` ASC
or
SELECT rental_plans.*,
( (inventory.total_inventory + vehicles.tmp_qty) - Ifnull(reservation.total_reserved, 0) ) AS vehicle_inventory
FROM `rental_plans`
INNER JOIN `vehicles`
ON `vehicles`.`id` = `rental_plans`.`vehicle_id`
LEFT JOIN
(
SELECT Count(*) AS total_inventory,
vehicle_id
FROM vehicle_inventories
GROUP BY vehicle_id) AS inventory
ON `inventory`.`vehicle_id` = `vehicles`.`id`
LEFT JOIN
(
SELECT vehicle_id,
Sum(qty) AS total_reserved
FROM `reservations`
WHERE (
'2018-12-18' BETWEEN pickup_date AND drop_date)
OR (
'2018-12-28' BETWEEN pickup_date AND drop_date)
AND `status` NOT IN ('RETURNED')
GROUP BY `vehicle_id`) AS `reservation`
ON `rental_plans`.`vehicle_id` = `reservation`.`vehicle_id`
WHERE `rental_plans`.`id` > 0
AND `rental_plans`.`pickup` = '1'
AND `rental_plans`.`drop` = '10'
where (
inventory.total_inventory + vehicles.tmp_qty) - ifnull(reservation.total_reserved, 0) > 16
ORDER BY `rental_plans`.`price` ASC
I want to retrieve a user's rank based on how many points the given user has compared to other users (simply counting users with more points than the given user).
However, with all the queries I have tried, I always end up with Column not found: users.id. From what I can read there is a limit from referencing correlated parent columns more than one level up.
Can I refactor my query, or do I really need to use SET #rownum := 0 style of queries?
SELECT
`users`.*,
(
SELECT COUNT(*) + 1
FROM (
SELECT SUM(`amount`) AS `all_points`
FROM `points`
WHERE `type` = ?
GROUP BY `user_id`
HAVING `all_points` > (
SELECT SUM(`amount`)
FROM `points`
WHERE `type` = ? and `user_id` = `users`.`id`
)
) `points_sub`
) as `rank`
FROM `users`
WHERE `users`.`id` = ?
LIMIT 1
You can move your sub clause one level up, Remove having filter and use where filter
SELECT
`users`.*,
(
SELECT COUNT(*) + 1
FROM (
SELECT user_id,SUM(`amount`) AS `all_points`
FROM `points`
WHERE `type` = ?
GROUP BY `user_id`
) `points_sub`
WHERE `all_points` >
SELECT SUM(`amount`)
FROM `points`
WHERE `type` = ? and `user_id` = `users`.`id`
) as `rank`
FROM `users`
WHERE `users`.`id` = ?
LIMIT 1
I think the below query should work for you. You can pass the user_id of user whose rank you want to compute in both the arguments.
SELECT
`users`.*,
(
SELECT COUNT(*) + 1
FROM (
SELECT SUM(`amount`) AS `all_points`
FROM `points`
WHERE `type` = ?
GROUP BY `user_id`
HAVING `all_points` > (
SELECT COALESCE(SUM(`amount`),0)
FROM `points`
WHERE `type` = ? and `user_id` = ?
)
) `points_sub`
) as `rank`
FROM `users`
WHERE `users`.`id` = ?
LIMIT 1
Why is this sql giving tables with minimum field having null. Also when A has no data between the given date ranges, it is providing the table with all rooms having minimum as null
SELECT `rooms`.*,A.`minimum`
FROM (
SELECT `room_id`, min(`available_rooms`) AS `minimum`
FROM `room_bookings`
WHERE `date` BETWEEN '2014-02-01' and '2014-02-10'
GROUP BY `room_id`) as A
INNER JOIN `rooms` on `rooms`.`room_id`=A.`room_id`
WHERE `rooms`.`location`='kathmandu'
AND `rooms`.`status`=1
AND A.`minimum`!=NULL
SELECT `rooms`.*,A.`minimum`
FROM (
SELECT `room_id`, min(`available_rooms`) AS `minimum`
FROM `room_bookings`
WHERE `date` BETWEEN '2014-02-01' and '2014-02-10'
GROUP BY `room_id` having minimum > 0) as A
INNER JOIN `rooms` on `rooms`.`room_id`=A.`room_id`
WHERE `rooms`.`location`='kathmandu'
AND `rooms`.`status`=1
SELECT `rooms`.*,A.`minimum`
FROM (
SELECT `room_id`, min(`available_rooms`) AS `minimum`
FROM `room_bookings`
WHERE `date` BETWEEN '2014-02-01' and '2014-02-10'
GROUP BY `room_id`) as A
INNER JOIN `rooms` on `rooms`.`room_id`=A.`room_id`
WHERE `rooms`.`location`='kathmandu'
AND `rooms`.`status`=1
AND A.`minimum` is not NULL
This would be the correct syntax ( change != to is not )
Try this:
SELECT r.*, MIN(rb.available_rooms) minimum
FROM rooms r
INNER JOIN room_bookings rb ON r.room_id = rb.room_id AND rb.date BETWEEN '2014-02-01' AND '2014-02-10'
WHERE r.location = 'kathmandu' AND r.status = 1
GROUP BY r.room_id HAVING minimum IS NOT NULL
try this with IS NOT NULL
SELECT `rooms`.*,A.`minimum`
FROM (
SELECT `room_id`, min(`available_rooms`) AS `minimum`
FROM `room_bookings`
WHERE `date` BETWEEN '2014-02-01' and '2014-02-10'
GROUP BY `room_id`) as A
INNER JOIN `rooms` on `rooms`.`room_id`=A.`room_id`
WHERE `rooms`.`location`='kathmandu'
AND `rooms`.`status`=1
AND A.`minimum` IS NOT NULL
Here's a SQL statement:
SELECT DISTINCT `class`, `student_id` , `student_name`,
(
SELECT SUM( `credits` )
FROM `stumgr_scores` B
JOIN `stumgr_courses` USING ( `course_id` )
WHERE `year` =2012 AND A.`student_id` = B.`student_id`
) AS `total_credits`,
(
SELECT SUM( `credits` * `final_score` )
FROM `stumgr_scores` C
JOIN `stumgr_courses` USING ( `course_id` )
WHERE `year` =2012 AND A.`student_id` = C.`student_id`
) AS `total_scores`
FROM `stumgr_scores` A
NATURAL JOIN `stumgr_students`
WHERE `year` =2012 AND `grade` =2011
You may discover that these two select statement which use aggregate functions are similar. So, I want to merge them into one as following:
SELECT DISTINCT `class`, `student_id` , `student_name`,
(
SELECT
SUM( `credits` ) AS `total_credits`,
SUM( `credits` * `final_score` ) AS `total_scores`
FROM `stumgr_scores` B
JOIN `stumgr_courses` USING ( `course_id` )
WHERE `year` =2012 AND A.`student_id` = B.`student_id`
) AS `something`
FROM `stumgr_scores` A
NATURAL JOIN `stumgr_students`
WHERE `year` =2012 AND `grade` =2011
Of course, the SQL statement above doesn't work and I don't know what to do.
Besides, the query is very slow because of large data, do you have any suggestions? Thanks a lot.
I have had to guess at your table structure slightly, but you should be able to simplify this query massively by using JOINs rather than correlated subqueries:
SELECT st.student_id,
st.student_name,
c.class,
SUM(sc.credits) AS total_credits,
SUM(sc.credits * sc.final_score) AS total_scores
FROM stumgr_students st
INNER JOIN stumgr_scores sc
ON sc.student_id = st.student_id
INNER JOIN stumgr_courses c
ON c.course_id = st.course_id
GROUP BY st.student_id, st.student_name, c.class;