Again on SQL dates conversion - mysql

I read a zilion of links on this matter, but the more I read the more I'm confused.
In my DB I have a date column, with 'YYYY-MM-DD' format. I need to count the occorrences of month+year change, regardless of days. I currently use:
$query = "SELECT COUNT(data) as visits, COUNT(DISTINCT data) as diffentDates ,MIN(data) as 'MIN', MAX(data) as 'MAX' FROM visiting ";
Where 'data' is the value in my column.
This works fine: I get the totals for visits, the number of different dates, the first and the last visit.
The problem comes with 'diffentDates'; it should only count the changes in 'YYMM'.
I tried to use something similar to: COUNT( DISTINCT ( FORMAT (data,'YYMM') ) ) as diffentDates
but it does not do what I need (actually it gives errors or selects all the dates anyway).
Which is is the correct function to apply to translate (and select and count) from 'YYYY-MM-DD' to 'YYMM' ?
Thanks

If the column data is a TIMESTAMP or DATE type, the following should work:
SELECT
COUNT(`data`) as visits,
COUNT(DISTINCT DATE_FORMAT(`data`,'%Y%m')) as diffentDates,
MIN(`data`) as 'MIN',
MAX(`data`) as 'MAX'
FROM `visiting`

Related

MySQL return summed values and a virtual column as (count - sum)

I have a table as follows:
log (log_id, log_success (bool), log_created)
I would like to SELECT and return 3 columns date success and no_success, where the former does not exist in table and finally aggregate them by day.
I have created this query:
SELECT
log_created as 'date'
COUNT(*) AS 'count',
SUM(log_success) AS 'success'
SUM('count' - 'success') AS 'no_success'
FROM send_log
GROUP BY DATE_FORMAT(log_created, '%Y-%m-%d');
Would I be able to achieve it with this query? Is my syntax correct?
Thanks.
You can't reuse an alias defined in the select within the same select clause. The reason for this is that it might not even have been defined when you go to access it. But, you easily enough can repeat the logic:
SELECT
log_created AS date,
SUM(log_success) AS success,
COUNT(*) - SUM(log_success) AS no_success,
FROM send_log
GROUP BY
log_created;
I don't know why you are calling DATE_FORMAT in the group by clause of your query. DATE_FORMAT is usually a presentation layer function, which you call because you want to view a date formatted a certain way. Since it appears that log_created is already a date, there is no need to call DATE_FORMAT on it when aggregating. You also should not even need in the select clause, because the default format for a MySQL date is already Y-m-d.
You must select DATE_FORMAT(log_created, '%Y-%m-%d') if you want to group by this.
Also you can get the no_success counter with SUM(abs(log_success - 1))
SELECT
DATE_FORMAT(log_created, '%Y-%m-%d') date,
SUM(log_success) log_success,
SUM(abs(log_success - 1)) no_success
FROM send_log
GROUP BY date;
See the demo

Select Query Error with Date

I have a mysql table like this with these sample data
I write this query
SELECT SUM(amount),DATE(date) FROM outgoings WHERE outgoings_type_id = '1'GROUP BY amount
I got the output like this
I want it not like this but like this(I did some photoshop edit to above one!)
The only change is I want the summation of amounts which are on same date..Others are normal way..Is it possible or not with some changes to my query..?
Try this, you do your sum(amount) and group by date.
SELECT SUM(amount),DATE(date) FROM outgoings WHERE outgoings_type_id = '1'GROUP BY DATE(date)
Your aggregate (sum or whatever) will be grouped by the date field then.
Also, I don't think you need to do DATE(date)
SELECT SUM(amount),date FROM outgoings WHERE outgoings_type_id = '1'GROUP BY date

Group different groups as the same and count?

I have the following query:
SELECT owner,
typeOwner,
type,
count(*) AS count
FROM myTable
GROUP BY typeOwner
ORDER BY count DESC
LIMIT 0, 30
Now , the typeOwner values = '<test>a</test>' but , some times the typeOwner field will have some string else like '<test>b</test>, how can i let this query count the <test>b</test> as a group of '<test>a</test>.
I want to make an exception for this, I mean typeOwner <test>a</test> AND typeOwner <test>b</test> should be counted as one row that have two count.
here's a fiddle : http://sqlfiddle.com/#!2/70053/1 , take look
actually these are should be grouped by <type></type><aId></aId>
"actually these are should be grouped by "
You can GROUP BY something relatively ugly like:
GROUP BY LEFT(typeOwner, position('<xType>' in typeOwner) -1)
But you are probably better off preprocessing the data in some fashion. I'm not sure how MySQL handles xml, but in SQL server I might extract the XML values into first class relation fields if I needed to do this sort of processing with any frequency.
sqlfiddle.com
Based on your sqlfiddle, this works
SELECT
left(typeOwner, instr(typeOwner, '<xType>')-1) as typeOwner,
owner,type, count(*) as count
FROM `test`
GROUP BY left(typeOwner, instr(typeOwner, '<xType>')-1)
ORDER BY count DESC
LIMIT 0 , 30

mysql max(date) not working

So i have this query that is supposed to return some information like price, open, close, etc.. for the LATEST entry.
SELECT * FROM History WHERE symbol = $symbol Having max(`date`);
But for whatever reason its not returning the correct information. It for some reason believes that the max date is 2013-02-14, but if i look at all the data the most recent is actually 2013-02-27.
in this particular case
$symbol = "AGNC"
Does the max function not work on date?
I think you want to have something like this. I'm not fan of doing this using ORDER BY clause because there are some possibilities (although much little) that records may have the same latest date entry.
SELECT *
FROM History
WHERE symbol = $symbol AND
date = (SELECT MAX(date) FROM History)
SQLFiddle Demo
My suggestion would be not using MAX at all; if what you want to do is only fetching the latest entry in the table, you could try:
SELECT * FROM History WHERE symbol = $symbol ORDER BY date DESC LIMIT 1;
This works perfectly as long as your date field is actually declared as a date-related MySQL field type, like date, datetime, etc.
As JW pointed out in his answer, you may want to add more fields in your ORDER BY statement to disambiguate records that have the exact same date.
Also, you may want to put $symbol in quotes if that's a string field (char, varchar, etc):
SELECT * FROM History WHERE symbol = '$symbol' ORDER BY date DESC LIMIT 1;
Cheers!
The following should do what you want:
SELECT *
FROM History h
WHERE symbol = $symbol and
`date` = (select max(`date`) from History where symbol = $symbol)
You may use alias table name:
SELECT *
FROM History
WHERE symbol = $symbol AND
date = (SELECT MAX(date) FROM History);

MySQL Running Total with COUNT

I'm aware of the set #running_sum=0; #running_sum:=#running_sum + ... method, however, it does not seem to be working in my case.
My query:
SELECT DISTINCT(date), COUNT(*) AS count
FROM table1
WHERE date > '2011-09-29' AND applicationid = '123'
GROUP BY date ORDER BY date
The result gives me unique dates, with the count of occurrences of application 123.
I want to keep a running total of the count, to see the accumulated growth.
Right now I'm doing this in PHP, but I want to switch it all to MySQL.
Using the method from the first line of this post simply duplicates the count, instead of accumulating it.
What am I missing?
P.S. The set is very small, only about 100 entries.
Edit: you're right ypercube:
Here's the version with running_sum:
SET #running_sum=0;
SELECT date, #running_sum:=#running_sum + COUNT(*) AS total FROM table1
WHERE date > '2011-09-29' AND applicationid = '123'
GROUP BY date ORDER BY date
count column ends up being the same as if I just printed COUNT(*)
Updated Answer
The OP asked for a single-query approach, so as not to have to SET a user variable separately from using the variable to compute the running total:
SELECT d.date,
#running_sum:=#running_sum + d.count AS running
FROM ( SELECT date, COUNT(*) AS `count`
FROM table1
WHERE date > '2011-09-29' AND applicationid = '123'
GROUP BY date
ORDER BY date ) d
JOIN (SELECT #running_sum := 0 AS dummy) dummy;
"Inline initialization" of user variables is useful for simulating other analytic functions, too. Indeed I learned this technique from answers like this one.
Original Answer
You need to introduce an enclosing query to tabulate the #running_sum over your COUNT(*)ed records:
SET #running_sum=0;
SELECT d.date,
#running_sum:=#running_sum + d.count AS running
FROM ( SELECT date, COUNT(*) AS `count`
FROM table1
WHERE date > '2011-09-29' AND applicationid = '123'
GROUP BY date
ORDER BY date ) d;
See also this answer.
SQL is notoriously poor at running totals. As your result set is in order, you are much better advised to append a calculated running total column on the client side. Nothing in SQL will be as performant as that.
The Running total can be easily calculated using the lib_mysqludf_ta UDF library.
https://github.com/mysqludf/lib_mysqludf_ta#readme