MYSQL REPORTING - mysql

is there a more efficent way to get rows fro ma table from the current week, last week, current month and current year to this
// current month
SELECT * FROM crm_tasks WHERE YEAR( date_completed ) = YEAR( CURDATE( ) ) AND MONTH( date_completed ) = MONTH( CURDATE( ) )
// current week
SELECT * FROM crm_tasks WHERE YEAR( date_completed ) = YEAR( CURDATE( ) ) AND WEEK( date_completed ) = WEEK( CURDATE( ) )
// last week
SELECT * FROM crm_tasks WHERE YEAR( date_completed ) = YEAR( CURDATE( ) ) AND WEEK( date_completed ) = WEEK( CURDATE( ) ) - 1
// current year
SELECT * FROM crm_tasks WHERE YEAR( date_completed ) = YEAR( CURDATE( ) )

You should be able to use a query similar to this
SELECT * FROM crm_tasks
WHERE date_completed >= #FirstDayOfYear AND date_completed < #FirstDayOfNextYear
Where #FirstDayOfYear and #FirstDayOfNextYear are filled in appropriately. If you have an index on date_created, this should work reasonably fast. This can be altered for any period you want to use.

Related

Highcharts dont display statistics with MySQL Query

Highcharts dont display statistics with MySQL Query
It Works:
$this->db->query("SELECT COUNT( gt ) as sayi , FROM_UNIXTIME( tarih, '$periyot' ) AS gun
FROM sayigoruntu
WHERE tarih >= DATE_SUB( CURDATE( ) , INTERVAL 1 MONTH ) and gt='$gt'".$sqlek."
GROUP BY gun
ORDER BY gun");
Output:
[[3582],[2062],[140],[4425],[294]]
$this->db->last_query() Result:
SELECT COUNT( gt ) as sayi , FROM_UNIXTIME( tarih, '%Y.%m.%d' ) AS gun FROM sayigoruntu WHERE tarih >= DATE_SUB( CURDATE( ) , INTERVAL 1 MONTH ) and gt='0' GROUP BY gun ORDER BY gun
This works without problems but this doesn't work (PHP):
if($siteid !=''){
$sqlek="and sid='".$siteid."'";
}
SQL Query:
SELECT COUNT( gt ) as sayi , FROM_UNIXTIME( tarih, '$periyot' ) AS gun
FROM sayigoruntu
WHERE tarih >= DATE_SUB( CURDATE( ) , INTERVAL 1 MONTH ) and gt='$gt'".$sqlek."
GROUP BY gun
ORDER BY gun
Output:
[[3582],[2062],[140],[4425],[294]]
$this->db->last_query() result:
SELECT COUNT( gt ) as sayi , FROM_UNIXTIME( tarih, '%Y.%m.%d' ) AS gun FROM sayigoruntu WHERE tarih >= DATE_SUB( CURDATE( ) , INTERVAL 1 MONTH ) and gt='0' GROUP BY gun ORDER BY gun
Same Output, Same Queries but not working. Error reason maybe ".$sqlek." on MySQL Query.
Is MySQL Query Right Or is this a Highcharts Error?
Your form is incorrect, it should be array of numbers or array of arrays but including x/y. Not an array of arrays with single value. How you refer your data to javascript?

SQL exception Parameter index out of range

I'm sending 4 values for the sql query through a jaggery script. Here is the sql query:
SELECT full_name , sum( amount ) AS total
FROM hourlyusage , user
WHERE DAY = DATE( DATE_SUB( NOW( ) , INTERVAL ? HOUR ) )
AND HOUR BETWEEN HOUR( DATE_SUB( NOW( ) , INTERVAL ? HOUR ) )
AND HOUR( DATE_SUB( NOW( ) , INTERVAL 1 HOUR ) )
AND hourlyusage.userIp = user.ip_address
AND (user.full_name LIKE '%?%' OR user.user_name LIKE '%?%') GROUP BY full_name
But it gives an exception like this.
Nested Exception:-
java.sql.SQLException: Parameter index out of range (3 > number of parameters, which is 2).
What would be the reason for that?
SELECT full_name , sum( amount ) AS total
FROM hourlyusage , user
WHERE DAY = DATE( DATE_SUB( NOW( ) , INTERVAL ? HOUR ) )
AND HOUR BETWEEN HOUR( DATE_SUB( NOW( ) , INTERVAL ? HOUR ) )
AND HOUR( DATE_SUB( NOW( ) , INTERVAL 1 HOUR ) )
AND hourlyusage.userIp = user.ip_address
AND (user.full_name LIKE ? OR user.user_name LIKE ?) GROUP BY full_name
You cannot use wildcard in the sql query so try to remove the wildcard from the sql and add it to the value.As you have done '%?%' in sql says that you need global match.Do that in your value not in sql query.

Issue with SQL getting Upcoming Birthdays

Can anyone fix the following SQL code, which gets upcoming birthdays:
SELECT *
FROM personal
WHERE 1 = ( FLOOR( DATEDIFF( DATE_ADD( DATE( NOW( ) ) , INTERVAL :interval DAY ) , dob ) / 365.25 ) ) -
( FLOOR( DATEDIFF( DATE_ADD( DATE( NOW( ) ) , INTERVAL -1 DAY ) , dob ) / 365.25 ) )
ORDER BY MONTH( dob ), DAY( dob )
LIMIT :rangeStart,:limit
It works aside from there is a bug with the ordering if the year rolls over. E.g. your in December checking ahead 1 month, then January birthday will get ordered before December.
I've seen a few posts on here about doing this, but none of them seem to get this part correct. I tried using the following ORDER BY clause, from another post and which seemed to work for someone else, but when I run it I get a syntax error:
ORDER BY ( MONTH(dob) > MONTH(NOW() OR ((MONTH(dob) = MONTH(NOW()) AND DAY(dob) >= DAY(NOW()) DESC, MONTH(dob), DAY(dob)
Updated answer ...
Thought of a cleaner way to accomplish this:
SELECT *
FROM (
SELECT *
,DATE_ADD( MAKEDATE( YEAR( NOW() ), DAYOFYEAR( dob ) )
,INTERVAL IF( DAYOFYEAR( dob ) < DAYOFYEAR( NOW() ), 1, 0 ) YEAR
)
AS next_birthday
FROM personal
) a
WHERE a.next_birthday < DATE_ADD( NOW(), INTERVAL :interval DAY )
ORDER BY a.next_birthday ASC
LIMIT :rangeStart,:limit
Explanation: next_birthday is calculated by taking this year's birthday and adding either 1 or 0 years to it depending on whether or not the birthday has already occurred this year - determined by IF( DAYOFYEAR( dob ) < DAYOFYEAR( NOW() ), 1, 0 ).
See it in action in SQLFiddle at http://sqlfiddle.com/#!9/b6471/1. Play with the number of days to see January after December.
Original answer ...
Add the following to your SELECT:
SELECT *
, CASE WHEN MAKEDATE( YEAR( CURRENT_DATE ), DAYOFYEAR( dob ) ) >= CURRENT_DATE
THEN MAKEDATE( YEAR( CURRENT_DATE ), DAYOFYEAR( dob ) )
ELSE DATE_ADD( MAKEDATE( YEAR( CURRENT_DATE ), DAYOFYEAR( dob ) ), INTERVAL 1 YEAR )
END AS next_birthday
then
ORDER BY next_birthday ASC
Rewriting your original query you get something like:
SELECT a.*
FROM ( SELECT *
, CASE WHEN DAYOFYEAR( dob ) >= DAYOFYEAR( CURRENT_DATE )
THEN MAKEDATE( YEAR( CURRENT_DATE ), DAYOFYEAR( dob ) )
ELSE DATE_ADD( MAKEDATE( YEAR( CURRENT_DATE ), DAYOFYEAR( dob ) ), INTERVAL 1 YEAR )
END AS next_birthday
FROM personal
) a
WHERE a.next_birthday < DATE_ADD( CURRENT_DATE, INTERVAL :interval DAY )
ORDER BY a.next_birthday ASC
LIMIT :rangeStart,:limit
I've now found a solution. For those that would like to know, the final code is:
SELECT *, DATE_ADD( dob, INTERVAL YEAR( FROM_DAYS( DATEDIFF( NOW( ), dob) -1 ) ) + 1 YEAR) AS next_birthday
FROM personal
WHERE 1 = ( FLOOR( DATEDIFF( DATE_ADD( DATE( NOW( ) ) , INTERVAL :interval DAY ) , dob ) / 365.25 ) ) -
( FLOOR( DATEDIFF( DATE_ADD( DATE( NOW( ) ) , INTERVAL -1 DAY ) , dob ) / 365.25 ) )
ORDER BY next_birthday ASC
LIMIT :rangeStart,:limit
I haven't tested it fully, but on simple tests it works.

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

Select time range from unix-timestamp

I have a MYSQL table with two columns, timestamp and span. timestamp is a unix-timestamp, while span is an integer.
I want to select all rows where the timestamp is between the current time +- half the span.
Eg. if the current time is 23:00, then I want all rows where the timestamp time is between 21 and 01. The issue is of-course that all the timestamps are from different days.
TO CLARIFY, I don't care about the date only the time
I've figured out a way to do this, but it seems like such a hack. I'm sure that someone with more MYSQL knowledge could show me a prettier way to do this.
SELECT *
FROM table
WHERE (
TIME( DATE_SUB( CURDATE( ) , INTERVAL( span /2 ) HOUR ) ) <= TIME( DATE_ADD( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
AND (
TIME( FROM_UNIXTIME( timestamp ) ) >= TIME( DATE_SUB( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
AND TIME( FROM_UNIXTIME( timestamp ) ) <= TIME( DATE_ADD( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
)
)
OR (
TIME( DATE_SUB( CURDATE( ) , INTERVAL( span /2 ) HOUR ) ) >= TIME( DATE_ADD( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
AND (
TIME( FROM_UNIXTIME( timestamp ) ) >= TIME( DATE_SUB( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
OR TIME( FROM_UNIXTIME( timestamp ) ) <= TIME( DATE_ADD( CURDATE( ) , INTERVAL( span /2 ) HOUR ) )
)
)
Two options I recommend.
Benchmark your "hack" query and see if that is faster than running two MySQL queries. Eg: One query to get your target row, another query to get results with ±1/2 span.
Write a proper MySQL stored procedure. This is effectively option (1) but all done inside the DB.
Another option I don't recommend, based on past pain, is to use MySQL variables to effectively do two selects avoiding the stored procedure, eg: http://dev.mysql.com/doc/refman/5.0/en/user-variables.html. This approach was common back in the old days of PHP/MySQL apps.
In my experience odds are good option (1) is both fast enough and readable.
Didn't really find a pretty solution, but this is how i ended up doing it.
SELECT *
FROM table
WHERE date_add( from_unixtime( timestamp ) , INTERVAL datediff( now( ) , from_unixtime( timestamp ) ) DAY )
BETWEEN date_sub( now( ) , INTERVAL (span/2) HOUR )
AND date_add( now( ) , INTERVAL (span/2) HOUR )
OR date_add( from_unixtime( timestamp ) , INTERVAL datediff( now( ) , from_unixtime( timestamp ) ) -1 DAY )
BETWEEN date_sub( now( ) , INTERVAL (span/2) HOUR )
AND date_add( now( ) , INTERVAL (span/2) HOUR )