I have a mysql query which works in a strange way. I am posting the 2 queries with input data changed and the output are listed under each query.
Query 1 (Area to be noted BETWEEN '13/05/11' AND '30/05/11'):
SELECT COUNT(pos_transaction_id) AS total,
DATE_FORMAT(pt.timestamp,'%d-%m-%Y %H:%i:%S') AS Date,
SUM(amount) AS amount
FROM pos_transactions pt
WHERE DATE_FORMAT(pt.timestamp,'%e/%m/%y') BETWEEN '13/05/11' AND '30/05/11'
GROUP BY WEEK(pt.timestamp) ORDER BY pt.timestamp
Output:
Query 2 (Area to be noted BETWEEN '3/05/11' AND '30/05/11'):
SELECT COUNT(pos_transaction_id) AS total,
DATE_FORMAT(pt.timestamp,'%d-%m-%Y %H:%i:%S') AS Date,
SUM(amount) AS amount
FROM pos_transactions pt
WHERE DATE_FORMAT(pt.timestamp,'%e/%m/%y') BETWEEN '3/05/11' AND '30/05/11'
GROUP BY WEEK(pt.timestamp) ORDER BY pt.timestamp
Output:
Now when the range is increased in the second query why am I getting just one record ? And even in the first query I am getting records which is out of range. What is wrong with it??
EDIT
The changed query looks like this and still not doing what I wanted it to do.
SELECT COUNT(pos_transaction_id) AS total,
DATE_FORMAT(pt.timestamp,'%d-%m-%Y %H:%i:%S') AS Date,
SUM(amount) AS amount
FROM pos_transactions pt
WHERE DATE_FORMAT(pt.timestamp,'%e/%m/%y') BETWEEN STR_TO_DATE('01/05/11','%e/%m/%y') AND STR_TO_DATE('30/05/11','%e/%m/%y')
GROUP BY WEEK(pt.timestamp) ORDER BY pt.timestamp
The output is:
I think you're seeing the result of the intersection of two bad practices.
First, the date_format() function returns a string. Your WHERE clause does a string comparison. In PostgreSQL
select '26/04/2011' between '13/05/11' AND '30/05/11';
--
T
That's because the string '26' is between the strings '13' and '30'. If you write them as dates, though, PostgreSQL will correctly tell you that '2011-04-26' (following the datestyle setting on my server) isn't in that range.
Second, I'm guessing that the odd out-of-range values appear because you're using an indeterminate expression in your aggregate. The expression WEEK(pt.timestamp) doesn't appear in the SELECT list. I think every other SQL engine on the market will throw an error if you try to do that. Since it's not in the SELECT list, MySQL will return an apparently random value from that aggregate range.
To avoid these kinds of errors, don't do string comparisons on date or timestamp ranges, and don't use indeterminate aggregate expressions.
Posting DDL and minimal SQL INSERT statements to reproduce the problem helps people help you.
I'm absolutely not sure, but it is maybe the comparison is done as a string and not as a date.
DATE_FORMAT returns a string and both your condition are strings too.
You should try without the DATE_FORMAT, just the column, or maybe trying to convert the condition to a date.
I'm thinking something like this :
pt.timestamp BETWEEN STR_TO_DATE('13/05/11', '%e/%m/%y') AND STR_TO_DATE('30/05/11', '%e/%m/%y')
I am pretty sure you are meaning to do
WHERE pt.timestamp BETWEEN TO_DATE('13/04/11', 'dd/mm/yy') AND TO_DATE('30/05/11', 'dd/mm/yy')
Before you are asking it for a string between two other strings.
Update
I think a few point is being missed here. Based on the calculations you are doing on pos_transactions.timestamp I am going to assume it's a type of timestamp. In your query you need to use the timestamp directly if you want to do a range compare. A timestamp already contains all the data you need to do this comparison. You don't need to covert it to Day/Month/Year to compare it.
What you need to do is this:
Find all values where my timestamp is between create a new date from '13/05/11' AND create a new date from '30/05/11'. pt.timestamp is already a timestamp, no need to convert it in your WHERE clause.
What you keep doing is converting it into a String representation. Thats ok when you want to display it, but not when you want to compare it with other values.
Related
This is my current table, let's call it "TABLE"
I want end result to be:
I tried this query:
SELECT * FROM TABLE GROUP BY(service)
but it doesn't work
i tried replacing NULL with 0 and then perform group by but "TBA" (text value) is creating problem, kindly help me out!
This looks like simple aggregation:
select service, max(for1) for1, max(for2) for2, max(for3) for3
from mytable
group by service
This takes advantage of the fact that aggregate functions such as max() ignore null values. However if a column has more than one non-null value for a given service, only the greatest will appear in the resultset.
It is unclear what the datatype of your columns is. Different datatypes have different rules for sorting.
I have written the below query.
SELECT bmr_multi_price. *
FROM bmr_multi_price
INNER JOIN bmr_rooms ON bmr_rooms.resort_id = bmr_multi_price.resort_id
AND bmr_rooms.id = bmr_multi_price.room_id
For this above query i have got the below result set.
But I wanted to include the below condition to achieve the above result.
WHERE ( '08/02/2013' BETWEEN bmr_multi_price.from_date AND bmr_multi_price.to_date ) OR ( '08/03/2013' BETWEEN bmr_multi_price.from_date AND bmr_multi_price.to_date )
If the query isn't returning expected results, the likely explanation is that you're comparing strings, and not dates.
The MySQL STR_TO_DATE function is a convenient way to convert strings in a given format into a DATE value. I'm going to guess that string represents a date in mm/dd/yyyy format, based on the values returned in the resultset.
STR_TO_DATE('08/12/2013','%m/%d/%Y')
If those columns are defined as character, rather that DATE, then you can convert them as well:
STR_TO_DATE(bmr_multi_price.from_date,'%m/%d/%y')
MySQL provides a DATE datatype which makes working with dates much easier and (usually) much more efficient.
I have a database that holds readings for devices. I am trying to write a query that can select the latest reading from a device. I have two queries that are seemingly the same and that I'd expect to give the same results; however they do not. The queries are as follows:
First query:
select max(datetime), reading
from READINGS
where device_id = '1234567890'
Second query:
select datetime, reading
from READINGS
where device_id = '1234567890' and datetime = (select max(datetime)
from READINGS
where device_id = '1234567890')
The they both give different results for the reading attribute. The second one is the one that gives the right result but why does the first give something different?
This is MySQL behaviour at work. When you use grouping the columns you select must either appear in the group by or be an aggregate function eg min(), max(). Mixing aggregates and normal columns is not allowed in most other database flavours.
The first query will just return the first rating in each group (first in the sense of where it appears on the file system), which is most likely wrong.
The second query correlates rating with maximum time stamp leading to the correct result.
It is because you are not using a GROUP BY reading clause, which you should be using in both queries.
This is normal on MySQL. See the documentation on this:
If you use a group function in a statement containing no GROUP BY clause, it is equivalent to grouping on all rows.
Also, read http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html
You can use the Explain and Explan extended commands to know more about your queries.
This simple SQL problem is giving me a very hard time. Either because I'm seeing the problem the wrong way or because I'm not that familiar with SQL. Or both.
What I'm trying to do: I have a table with several columns and I only need two of them: the datetime when the entry was created and the id of the entry. Note that the hours/minutes/seconds part is important here.
However, I want to group my selection according to the DATE part only. Otherwise all groups will most likely have 1 element.
Here's my query:
SELECT MyDate as DateCr, COUNT(Id) as Occur
FROM MyTable tb WITH(NOLOCK)
GROUP BY CAST(tb.MyDate as Date)
ORDER BY DateCr ASC
However I get the following error from it:
Column "MyTable.MyDate" is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
If I don't do the cast in the GROUP BY, everything fine. If I cast MyDate to DATE in the SELECT and keep the CAST from GROUP BY, everything fine once more. Apparently it wants to keep the same DATE or DATETIME format in the GROUP BY as in the SELECT.
My approach can be completely wrong so I am not necessarily looking to fix the above query, but to find the proper way to do it.
LE: I get the above error on line 1.
LE2: On a second look, my question indeed is not very explicit. You can ignore the above approach if it is completely wrong. Below is a sample scenario
Let me tell you what I need: I want to retrieve (1) the DateTime when each entry was created. So if I have 20 entries, then I want to get 20 DateTimes. Then if I have multiple entries created on the same DAY, I want the number of those entries. For example, let's say I created 3 entries on Monday, 1 on Tuesday and 2 today. Then from my table I need the datetimes of these 6 entries + the number of entries which were created on each day (3 for 19/03/2012, 1 for 20/03/2012 and 2 for 21/03/2012).
I'm not sure why you're objecting to performing the CONVERT in both the SELECT and the GROUP BY. This seems like a perfectly logical way to do this:
SELECT
DateCr = CONVERT(DATE, MyDate),
Occur = COUNT(Id)
FROM dbo.MyTable
GROUP BY CONVERT(DATE, MyDate)
ORDER BY DateCr;
If you want to keep the time portion of MyDate in the SELECT list, why are you bothering to group? Or how do you expect the results to look? You'll have a row for every individual date/time value, where the grouping seems to indicate you want a row for each day. Maybe you could clarify what you want with some sample data and example desired results.
Also, why are you using NOLOCK? Are you willing to trade accuracy for a haphazard turbo button?
EDIT adding a version for the mixed requirements:
;WITH d(DateCr,d,Id) AS
(
SELECT MyDate, d = CONVERT(DATE, MyDate), Id
FROM dbo.MyTable)
SELECT DateCr, Occur = (SELECT COUNT(Id) FROM d AS d2 WHERE d2.d = d.d)
FROM d
ORDER BY DateCr;
Even though this is an old post, I thought I would answer it. The solution below will work with SQL Server 2008 and above. It uses the over clause, so that the individual lines will be returned, but will also count the rows grouped by the date (without time).
SELECT MyDate as DateCr,
COUNT(Id) OVER(PARTITION BY CAST(tb.MyDate as Date)) as Occur
FROM MyTable tb WITH(NOLOCK)
ORDER BY DateCr ASC
Darren White
I have a table like this :
And in this table you can see the last column totalloginFinal, I want to do the sum of all time, its will be about 84 hours,
I am trying with addtime and sum function but not getting proper result.
Thanks a lot in Advance.
Try this variant -
SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(totalloginFinal))) FROM table_name;
From the reference - The SUM() and AVG() aggregate functions do not work with temporal values. (They convert the values to numbers, which loses the part after the first non-numeric character.) To work around this problem, you can convert to numeric units, perform the aggregate operation, and convert back to a temporal value.
GROUP BY (Aggregate) Functions.
try convert it to second and then sum the seconds and convert it back from second to time
like :
SELECT SEC_TO_TIME(SUM(SECOND(totalloginFinal))) as Total from mytable