MySQL Syntax Error (Completely new to this) - mysql

When I run the following query:
SELECT MONTHNAME( start_date_time ) AS
MONTH, SUM (
CASE WHEN YEAR( start_date_time ) = '2011' AND YEAR( u.registered) = '2011'
THEN oi.qty
END )
AS '2011', SUM (
CASE WHEN YEAR( start_date_time ) = '2012' AND YEAR( u.registered) = '2012'
THEN oi.qty
END )
AS '2012', SUM (
CASE WHEN YEAR( start_date_time) = '2013' AND YEAR( u.registered) = '2013'
THEN oi.qty
END )
) AS '2013'
FROM order_items oi INNER JOIN events e ON oi.eventid = e.eventid INNER JOIN company_campaign ON e.event_campaign_id = company_campaign.campaignid
INNER JOIN company
ON company.companyid = company_campaign.companyid
INNER JOIN users u
ON u.userID = company.createdby
WHERE start_date_time > '2011-01-01 00:00:00'
GROUP BY MONTH
ORDER BY MONTH( start_date_time ) ASC
I get the error:
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') AS '2013' FROM order_items oi INNER JOIN events e ON oi.eventid = e.eventid ' at line 18
I'm completely new to SQL and the join represented my greatest achievement to date, but this has completely stumped me. Sometimes I use the wrong type of ' but it's the right one here. Also sometimes I put a , at the end of the query. I'm using MySQL 5.5

Looks like an extra closing parenthesis (just before AS 2013) is causing this.
Try:
SELECT MONTHNAME( start_date_time ) AS
MONTH,
SUM ( CASE WHEN YEAR( start_date_time ) = '2011' AND YEAR( u.registered ) = '2011'
THEN oi.qty END )
AS '2011',
SUM ( CASE WHEN YEAR( start_date_time ) = '2012' AND YEAR( u.registered ) = '2012'
THEN oi.qty END )
AS '2012',
SUM ( CASE WHEN YEAR( start_date_time) = '2013' AND YEAR( u.registered ) = '2013'
THEN oi.qty END )
AS '2013'
FROM order_items oi INNER JOIN events e ON oi.eventid = e.eventid INNER JOIN company_campaign ON e.event_campaign_id = company_campaign.campaignid
INNER JOIN company
ON company.companyid = company_campaign.companyid
INNER JOIN users u
ON u.userID = company.createdby
WHERE start_date_time > '2011-01-01 00:00:00'
GROUP BY MONTH
ORDER BY MONTH( start_date_time ) ASC

Extra close bracket before 'As 2013'
) AS '2013'
Remove that and it should be fine.
Just to add - it always makes it much easier reading queries if you separate out your bracketed sections. Takes a bit longer and adds more lines but it will make it so much easier to read (and to spot syntax issues) for other people or for yourself when you come back to it in the future.
e.g. written like this it is immediately obvious where the problem is -
SELECT
MONTHNAME( start_date_time ) AS MONTH,
SUM
(
CASE WHEN YEAR( start_date_time ) = '2011' AND YEAR( u.registered) = '2011'
THEN oi.qty
END
) AS '2011',
SUM
(
CASE WHEN YEAR( start_date_time ) = '2012' AND YEAR( u.registered) = '2012'
THEN oi.qty
END
) AS '2012',
SUM
(
CASE WHEN YEAR( start_date_time) = '2013' AND YEAR( u.registered) = '2013'
THEN oi.qty
END
)
) AS '2013'

Related

MySQL get single column value of last record

I have a query which looks like:
SELECT max(sp.id) as max_id, p.name as player, max(update_time) as last_seen, min(login_time) as first_seen, s.name as last_server,
sum(sp.play_time) as ontime_total,
sum(case when login_time > NOW() - INTERVAL 1 DAY then sp.play_time end) as ontime_day,
sum(case when login_time > NOW() - INTERVAL 7 DAY then sp.play_time end) as ontime_week,
sum(case when login_time > NOW() - INTERVAL 1 MONTH then sp.play_time end) as ontime_month
FROM session_player sp
INNER JOIN players p ON p.id=sp.player_id
INNER JOIN server s ON s.id=sp.server_id
WHERE p.name = ?
The result:
The issue:
Node22 isn't the last server. I am struggling on finding a way to get the server of the last record within this query. How would you solve this issue, if possible without running a second query.
(This query already takes 2-3s seconds depending on the user, if possible I would like to avoid any overhead and in case you see performance optimization possibilities I would appreciate anything.)
This would work, but its performance you can guess (4-5s):
SELECT
MAX( sp.id ) AS max_id, p.name AS player, MAX( update_time ) AS last_seen, MIN( login_time ) AS first_seen,
SUM( sp.play_time ) AS ontime_total,
SUM( CASE WHEN login_time > NOW( ) - INTERVAL 1 DAY THEN sp.play_time END ) AS ontime_day,
SUM( CASE WHEN login_time > NOW( ) - INTERVAL 7 DAY THEN sp.play_time END ) AS ontime_week,
SUM( CASE WHEN login_time > NOW( ) - INTERVAL 1 MONTH THEN sp.play_time END ) AS ontime_month,
(SELECT s.name
FROM session_player sp
JOIN players p ON p.id=sp.player_id
JOIN server s ON s.id=sp.server_id
WHERE p.name = ?
ORDER BY sp.id DESC
LIMIT 1
) as last_server
FROM session_player sp
INNER JOIN players p ON p.id = sp.player_id
INNER JOIN server s ON s.id = sp.server_id
WHERE p.name = ?
After nearly 3 hours of experimenting I got it and even 260 times faster as before:
SELECT MAX(pd.id) AS max_id, pd.name AS player, MAX( pd.update_time ) AS last_seen, MIN( pd.login_time ) AS first_seen,
SUM( pd.play_time ) AS ontime_total,
SUM( CASE WHEN pd.login_time > NOW( ) - INTERVAL 1 DAY THEN pd.play_time END ) AS ontime_day,
SUM( CASE WHEN pd.login_time > NOW( ) - INTERVAL 7 DAY THEN pd.play_time END ) AS ontime_week,
SUM( CASE WHEN pd.login_time > NOW( ) - INTERVAL 1 MONTH THEN pd.play_time END ) AS ontime_month,
(SELECT s.name
FROM session_player sp
INNER JOIN server s ON s.id=sp.server_id
WHERE max(pd.id)=sp.id
) as last_server
FROM (
SELECT sp.id AS id, sp.server_id as server_id, p.name AS name, sp.login_time AS login_time, sp.update_time AS update_time, sp.play_time AS play_time
FROM session_player sp
INNER JOIN players p ON p.id=sp.player_id
WHERE p.name = ?
) as pd
Try this:
SELECT sp.id as max_id, p.name as player, max(update_time) as last_seen,
min(login_time) as first_seen, s.name as last_server,
sum(sp.play_time) as ontime_total,
sum(case when login_time > NOW() - INTERVAL 1 DAY then sp.play_time end) as ontime_day,
sum(case when login_time > NOW() - INTERVAL 7 DAY then sp.play_time end) as ontime_week,
sum(case when login_time > NOW() - INTERVAL 1 MONTH then sp.play_time end) as ontime_month
FROM session_player sp
INNER JOIN players p ON p.id=sp.player_id
INNER JOIN server s ON s.id=sp.server_id
WHERE p.name = ?
group by sp.player_id
order by sp.id desc limit 1

Mysql Joins with nested Select

I am trying to get the total of all orders of each seller per year, month, and day using this sql. I am still wrapping my head around joins, but from what I know i thought this should work
SELECT sellers.username, sellers.registerDate, sellers.sellerid,
orders.orderPrice, orders.orderDate, orders.sellerid,
count(orders.orderPrice) AS products, SUM( orders.orderPrice ) AS total,
FROM `sellers`
JOIN
`orders`,
(SELECT SUM( orders.orderPrice ) FROM `orders` WHERE YEAR( orderDate ) = YEAR( CURDATE( ) ) ) AS year,
(SELECT SUM( orders.orderPrice ) FROM `orders` WHERE MONTH( orderDate ) = MONTH( CURDATE( ) ) ) AS month,
(SELECT SUM( orders.orderPrice ) FROM `orders` WHERE orderDate = CURDATE() ) AS day
ON orders.sellerid = sellers.sellerid
GROUP BY sellers.username
HAVING total > 0
ORDER BY total desc
LIMIT 0 , 4
But it gives me an error (#1064 - near 'ON orders.sellerid = sellers.sellerid GROUP BY sellers.username HAVING' at line 9)
You need to set ON clause on every join table not only the lastone.
Regards
JOIN
`orders` ON ??? = ???,
(SELECT SUM( orders.orderPrice ) FROM `orders` WHERE YEAR( orderDate ) = YEAR( CURDATE( ) ) ) AS year ON orders.sellerid = sellers.sellerid,
(SELECT SUM( orders.orderPrice ) FROM `orders` WHERE MONTH( orderDate ) = MONTH( CURDATE( ) ) ) AS month ON orders.sellerid = sellers.sellerid,
(SELECT SUM( orders.orderPrice ) FROM `orders` WHERE orderDate = CURDATE() ) AS day
ON orders.sellerid = sellers.sellerid

MySQL Can I merge these two queries together?

I want to get the results of these two queries together but can't figure out how to combine them. The goal is to get the total sales per month by product. I have instore purchases and online orders. Here is the first query to get the total sales per month from online orders:
SELECT YEAR( orderDate ) AS "SalesYear"
, MONTH( orderDate ) AS "SalesMonth"
, SUM( orderTotal ) AS "TotalSales"
, products.productID
FROM orders
INNER JOIN orderdetails ON orders.orderID = orderDetails.orderID
INNER JOIN products ON orderDetails.productID = products.productID
GROUP BY productID, YEAR( orderDate ) , MONTH( orderDate )
ORDER BY YEAR( orderDate ) , MONTH( orderDate )
Here is the query that retrieves total sales per month by product from in store purchases:
SELECT YEAR( orderDate ) AS "SalesYear"
, MONTH( orderDate ) AS "SalesMonth"
, SUM( orderTotal ) AS "TotalSales"
, products.productID
FROM in_storepurchase
INNER JOIN instorepurchasedetails
ON in_storepurchase.isPurchaseID = instorepurchasedetails.isPurchaseID
INNER JOIN products
ON instorepurchasedetails.productID = products.productID
GROUP BY productID, YEAR( orderDate ) , MONTH( orderDate )
ORDER BY YEAR( orderDate ) , MONTH( orderDate )
Any help on how I could get this into one query so I can get all the results on a single table would be appreciated.
Of course, you can use UNION:
SELECT
YEAR( t.orderDate ) AS "SalesYear", MONTH( t.orderDate ) AS "SalesMonth", SUM( t.orderTotal ) AS "TotalSales", productID
FROM
(
select 1
UNION ALL
select 2
) as t
GROUP BY
t.productID, YEAR( t.orderDate ) , MONTH( t.orderDate )

Same month two different SUMS

I'm trying to get different Sums for same month on same Year, just to get sums by different types. Tried using this code:
SELECT a.invoice_type, year( a.date ) AS Year,
date_format( a.date, '%M' ) AS `month` ,
Sum( x.amount * x.price ) AS sum FROM records x
JOIN paper_invoice a ON x.invoice_id = a.invoice_id
WHERE year( a.date ) = '2012'
GROUP BY a.invoice_type, Year( a.date ) , Month( a.date ) LIMIT 0 , 30
but it gives results in different rows:
http://www.part.lt/img/1505f0f13172922150febede85ddbf0925.png
But I need it to look like:
Year | Month | SUM_GRYNAIS | SUM_PAVEDIMU
2012 | January | 7597.14997705445 | 58740.2800849304
and ETC.
Try this:
SELECT Year, Month,
MAX(CASE WHEN invoice_type = 'GRYNAIS' THEN sum END) As Sum_GRYNAIS
MAX(CASE WHEN invoice_type = 'PAVEDIMU' THEN sum END) As SUM_PAVEDIMU
FROM
(
SELECT a.invoice_type, year( a.date ) AS Year,
date_format( a.date, '%M' ) AS `month` , Sum( x.amount * x.price ) AS sum
FROM records x JOIN paper_invoice a ON x.invoice_id = a.invoice_id
WHERE year( a.date ) = '2012' GROUP BY a.invoice_type, Year( a.date ) ,
Month( a.date ) LIMIT 0 , 30
)
GROUP BY Year, Month
Because each month has a different value. Try Group By on just the field year.
You are basically looking for PIVOT. MySql doesn't have a PIVOT function but you can still accomplish this. Here is an example of a PIVOT in MySql:
http://www.artfulsoftware.com/infotree/queries.php#78

Setting user defined variables with joins

I have a query like below:
Result gives #sold_count:=SUM(I.quantity) = 10, but #sold_count = 0,
so calculations are all 0.
What should be wrong here?
SET #sold_count :=0;
SELECT
#sold_count:=SUM(I.quantity),
#sold_count,I.from_widget,COUNT(from_widget) as order_count,
(#sold_count * buy_price) as ciro,
(#sold_count * list_price) as liste_ciro,
(#sold_count * widget_price) as vitrin_ciro,
P.*
FROM
tbl_products P
LEFT JOIN tbl_order_items I on I.product_id = P.id
WHERE
P.publish_date BETWEEN DATE_SUB( CURDATE( ) ,INTERVAL 3 MONTH ) AND DATE_SUB( CURDATE( ) ,INTERVAL 0 MONTH )
GROUP BY I.from_widget,I.product_id
ORDER BY publish_date DESC
Don't use variables. Just:
SELECT
SUM(I.quantity),
I.from_widget,
COUNT(from_widget) AS order_count,
SUM(I.quantity) * buy_price AS ciro,
SUM(I.quantity) * list_price AS liste_ciro,
SUM(I.quantity) * widget_price AS vitrin_ciro,
P.*
FROM
tbl_products P
LEFT JOIN tbl_order_items I
ON I.product_id = P.id
WHERE
P.publish_date BETWEEN DATE_SUB( CURDATE( ) , INTERVAL 3 MONTH )
AND DATE_SUB( CURDATE( ) , INTERVAL 0 MONTH )
GROUP BY I.from_widget,
I.product_id
ORDER BY publish_date DESC ;
You could also make the query a nested one, if you don't like using SUM(quantity) many times:
SELECT
sum_quantity * buy_price AS ciro,
sum_quantity * list_price AS liste_ciro,
sum_quantity * widget_price AS vitrin_ciro,
tmp.*
FROM
( SELECT
SUM(I.quantity) AS sum_quantity,
I.from_widget,
COUNT(from_widget) AS order_count,
buy_price,
list_price,
widget_price,
P.*
FROM
tbl_products P
LEFT JOIN tbl_order_items I
ON I.product_id = P.id
WHERE
P.publish_date BETWEEN DATE_SUB( CURDATE( ) , INTERVAL 3 MONTH )
AND DATE_SUB( CURDATE( ) , INTERVAL 0 MONTH )
GROUP BY I.from_widget,
I.product_id
) AS tmp
ORDER BY publish_date DESC ;