View hook only displays 1969 dates - mysql

I have a table that looks like:
+--------------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+-------------+------+-----+---------+-------+
| ProductsDownloadId | int(11) | NO | PRI | 0 | |
| RCContactID | int(11) | NO | MUL | NULL | |
| product_name | varchar(50) | YES | MUL | NULL | |
| download_date | timestamp | YES | | NULL | |
+--------------------+-------------+------+-----+---------+-------+
I'm writing a module for this table to be viewable in a Drupal 6 View.
I followed the example I found here:
http://drupalcontrib.org/api/drupal/contributions--views--docs--docs.php/function/hook_views_data/6
So I exposed the download_date as thus:
$data['products_downloaded']['download_date']=array(
'title'=>t("Download Date"),
'help'=>t("When Product was downloaded by the user"),
'field' => array(
'handler' => 'views_handler_field_date',
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
);
But when I add it to a view, all the dates are displayed as "12/31/1969 - 19:33". And none of the dates in my table are:
EDIT: Corrected query:
mysql> select count(1) from products_downloaded where download_date <'2000-12-31 23:59:59.999999';
+----------+
| count(1) |
+----------+
| 0 |
+----------+
1 row in set (0.04 sec)
I also did a custom date format with the format 'r' in the View and I got
Wed, 31 Dec 1969 19:33:31 -0500 for all the dates.
So what did I do wrong on my module?

Your query:
select count(1) from products_downloaded where download_date <'12/31/2000 - 19:33'
Your problem here is that MySQL expects dates to be given in a different format to that.
You need to provide your dates in the following format:
'2007-12-31 23:59:59.999999'
(you can drop the microseconds, seconds, etc to get the precision you need as required)
So in your case, your query should look like this:
select count(1) from products_downloaded where download_date <'2000-12-31 19:33'
This should query the field correctly.
By the way -- If you have dates showing up unexpectedly as 1969, it implies that perhaps you've been using the wrong format in other queries as well. You may want to check that too.
See the MySQL manual page for date times: http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html

What I was able to determine was that PHP or Drupal wasn't able to understand whatever was being returned to the processor. I messed around with a custom hook and got the value to be accepted by the DateTime constructor. From there . . . it was easy to get the date formats back.

Related

MySQL: selecting dates (from timestamp) for which condition (related to other fields in the row) is fulfilled

My SQL knowledge is rather weak and I come from procedural programming, so bear with me. I have a database that contains data from a weather station - these are collected each minute and the (important part of the) table is
MariaDB [weather]> describe readings;
+------------------+------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+------------+------+-----+-------------------+-------+
| time | timestamp | NO | PRI | CURRENT_TIMESTAMP | |
| inside_temp | float | YES | | NULL | |
| outside_temp | float | YES | | NULL | |
+------------------+------------+------+-----+-------------------+-------+
I want to find all days where the outside_temp was not lower and not larger than some values.
I can code it externally using MySQL for queries like
select min(outside_temp), max(outside_temp) from readings where date(time)='2022-01-27';
and iterating over all days in the database to check temperature values for each day separately, but I wonder if it is possible to do the selection just using MySQL command (I suppose it is, just beyond my imagination).
Something like select date(time), min(outside_temp), max(outside_temp) from readings group by date(time); would give you all timestamps that meet the requirements

How to add Time series queries with grafana and MySQL?

I'm new to grafana and playing around to see if it could fit my needs for a research lab.
I'm using grafana-server Version 4.5.2 (commit: ec2b0fe)
I tried to follow the grafana documentation about mysql datasources (sorry I'm not allowed to post more than two links, just try to search in your favorite search engine...)
I have succefully added a MySQL data source.
Here is my database :
mysql> DESC meteo;
+-------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+----------------+
| id | int(100) | NO | PRI | NULL | auto_increment |
| date_insert | datetime | NO | | NULL | |
| temperature | float | NO | | NULL | |
+-------------+----------+------+-----+---------+----------------+
Following the documentation I've added a panel "Table" with the following query...
SELECT
date_insert as 'Date',
temperature as 'Temperature'
FROM meteo
...and choosen "Format as Table"
The result is ok as you can see.
Grafana Panel Format Table
Now I would like to have a graph like this :
Grafana Panel Format Time series
How can I achieve this with my database ? I don't understand the doc which says :
If you set Format as to Time series, for use in Graph panel for example,
then there are some requirements for what your query returns.
Must be a column named time_sec representing a unix epoch in seconds.
Must be a column named value representing the time series value.
Must be a column named metric representing the time series name.
How can I apply this with my database ? Is it just possible ?
Here is the solution, thanks to the Grafana team !
daniellee's answer

Truncate column names in SELECT (MySQL client)

When I'm looking into new databases to explore what is there, usually I get tables with long column names but short contents, like:
mysql> select * from Seat limit 2;
+---------+---------------------+---------------+------------------+--------------+---------------+--------------+-------------+--------------+-------------+---------+---------+----------+------------+---------------+------------------+-----------+-------------+---------------+-----------------+---------------------+-------------------+-----------------+
| seat_id | seat_created | seat_event_id | seat_category_id | seat_user_id | seat_order_id | seat_item_id | seat_row_nr | seat_zone_id | seat_pmp_id | seat_nr | seat_ts | seat_sid | seat_price | seat_discount | seat_discount_id | seat_code | seat_status | seat_sales_id | seat_checked_by | seat_checked_date | seat_old_order_id | seat_old_status |
+---------+---------------------+---------------+------------------+--------------+---------------+--------------+-------------+--------------+-------------+---------+---------+----------+------------+---------------+------------------+-----------+-------------+---------------+-----------------+---------------------+-------------------+-----------------+
| 4897 | 2016-09-01 00:05:54 | 330 | 331 | NULL | NULL | NULL | 0 | NULL | NULL | 0 | NULL | NULL | NULL | 0.00 | NULL | NULL | free | NULL | NULL | 0000-00-00 00:00:00 | NULL | NULL |
| 4898 | 2016-09-01 00:05:54 | 330 | 331 | NULL | NULL | NULL | 0 | NULL | NULL | 0 | NULL | NULL | NULL | 0.00 | NULL | NULL | free | NULL | NULL | 0000-00-00 00:00:00 | NULL | NULL |
+---------+---------------------+---------------+------------------+--------------+---------------+--------------+-------------+--------------+-------------+---------+---------+----------+------------+---------------+------------------+-----------+-------------+---------------+-----------------+---------------------+-------------------+-----------------+
Since the length of the header is longer that the contents of each row, I see a unformatted output which is hard to standard, specially when you search for little clues like fields that aren't being used and so on.
Is there any way to tell mysql client to truncate column names automatically, for example, to 10 characters as maximum? With the first 10 character is usually enough to know which column they refer to.
Of course I could stablish column aliases for that with AS, but if there's too much columns and you want to do a fast exploration, that would take too long for each table.
Other solution will be to tell mysql to remove the prefix seat_ for each column for example (of course, for each column I would need to change the used prefix).
I don't think there's any way to do that automatically. Some options are:
1) Use a graphical UI such as PhpMyAdmin to view the table contents. These typically allow you to adjust column widths.
2) End the query with \G instead of ;:
mysql> SELECT * FROM seat LIMIT 2\G
This will display the columns horizontally instead of vertically:
seat_id: 4897
seat_created: 2016-09-01 00:05:54
seat_event_id: 330
...
I often use the latter for tables with lots of columns because reading the horizontal format can be difficult, especially when it wraps around on the terminal.
3) Use the less pager in a mode that doesn't wrap lines. You can then scroll left and right with the arrow keys.
mysql> pager less -S
See How to better display MySQL table on Terminal
You can skip the column names completely by running the MySQL client with the -N or --skip-column-names option. Then the width of your columns will be determined by the widest data, not the column name. But there would be no row for the column names.
You can also use column aliases to set your own column names, but you'd have to enter these yourself manually.

MySQL: Incorrect Date Value

I am parsing an xml file that has following data structure:
<row Id="253858" UserId="40883" Name="Scholar" Date="2009-03-08T01:52:32.570" />
<row Id="253860" UserId="19483" Name="Supporter" Date="2009-03-08T01:57:31.733" />
<row Id="253861" UserId="74951" Name="Autobiographer" Date="2009-03-08T02:02:32.390" />
I used a ruby script to parse this data and insert them into a mysql database. Here is how my data table looks like:
+---------+-------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+-------------------+-----------------------------+
| id | int(11) | NO | PRI | NULL | |
| user_id | int(11) | NO | | NULL | |
| name | varchar(40) | YES | | NULL | |
| created | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+---------+-------------+------+-----+-------------------+-----------------------------+
This xml file has large number of records and until the parser gets to 3rd record I don't get any error and all the data get parse correctly and insert into the table:
| 253857 | 23658 | Critic | 2009-03-08 01:52:32 |
| 253858 | 40883 | Scholar | 2009-03-08 01:52:33 |
| 253860 | 19483 | Supporter | 2009-03-08 01:57:32 |
+--------+---------+--------------------+---------------------+
But when we get to the record with row Id="253861" I get the following mysql error:
load.rb:21:in `execute': Incorrect datetime value: '2009-03-08T02:02:32.390' for column 'created' at row 1 (Mysql::Error)
from load.rb:21:in `on_start_element'
from load.rb:133:in `parse'
from load.rb:133:in `<main>'
incase if you need the ruby method that insert records:
def on_start_element(element, attributes)
if element == 'row'
#st.execute(attributes['Id'], attributes['UserId'], attributes['Name'], attributes['Date'])
end
end
end
I don't think this is related to script, because I extracted the record from xml file and tried to insert directly into my mysql table and I got the following error:
mysql> insert into badge values(253861,74951,'Autobiographer','2009-03-08T02:02:32.390');
ERROR 1292 (22007): Incorrect datetime value: '2009-03-08T02:02:32.390' for column 'created' at row 1
I also tried to insert the record that is after the above record in the xml file and I got the same results:
mysql> insert into badge values(253862,49628,'Teacher','2009-03-08T02:12:30.807');
ERROR 1292 (22007): Incorrect datetime value: '2009-03-08T02:12:30.807' for column 'created' at row 1
So something in that date string makes mysql unhappy. What I couldn't figure out is that date and previous records that has the same date structure didn't have any problem. Hope I have explain the problem clear with information.
Since you said you insert dates in a couple of places I would suggest you write and helper method to do date conversions that you can reuse everywhere you need to insert dates
require 'date'
def iso8601_to_mysql_datetime(date)
DateTime.parse(date).to_time.strftime("%F %T")
end
iso8601_to_mysql_datetime('2009-03-08T02:02:32.390')
=> "2009-03-08 02:02:32"
NOTE: The above converts a ISO8601 into a string that MySQL understands
MySQL date and time literal documentation can be found here:
http://dev.mysql.com/doc/refman/5.6/en/date-and-time-literals.html

Can I SELECT this in a single stament?

I am a total SQL noob; sorry.
I have a table
mysql> describe activity;
+--------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+-------+
| user | text | NO | | NULL | |
| time_stamp | int(11) | NO | | NULL | |
| activity | text | NO | | NULL | |
| item | int | NO | | NULL | |
+--------------+---------+------+-----+---------+-------+
Normally activity is a two-step process; 1) "check out" and 2 "use"
An item cnnot be checked out a second time, unless used.
Now I want to find any cases where an item was checked out but not used.
Being dumb, I would use two selects, one for check out &one for use, on the same item, then compare the timestamps.
Is there a SELECT statemnt that will help me selct the items which were checked out but not used?
Tricky with the possibility of multipel checkouts. Or should I just code
loop over activity, form oldest until newset
if find a checkout and there is no newer used time then i have a hit
You could get the last date of each checkout or use and then compare them per item:
SELECT MAX(IF(activity='check out', time_stamp, NULL)) AS last_co,
MAX(IF(activity='use', time_stamp, NULL)) AS last_use
FROM activity
GROUP BY item
HAVING NOT(last_use >= last_co);
The NOT(last_use >= last_co) is written that way because of how NULL compare behaviour works: last_use < last_co will not work if last_use is null.
Without proper indexing, this query will not perform very well though. Plus you might want to bound the query using a WHERE condition.