running into "unknown tablefield" but it is defined - mysql

running a query and converting the stored unix-time-stamp to the certain date-format. this i wanna compare with the timestamp of today...
i am running within the where condition into the error that "D" is not known?
SELECT
COUNT(distinct db_suid),
date_format(from_unixtime(d_utime),'%H') AS H,
date_format(from_unixtime(d_utime),'%Y-%m-%d') AS D
FROM air_vault
WHERE CURRENT_DATE = D
GROUP BY H
at the end i wanna get the distinct number of values per hour of today

You can't use alias defined in select also in where clause
SELECT
COUNT(distinct db_suid),
date_format(from_unixtime(d_utime),'%H') AS H,
date_format(from_unixtime(d_utime),'%Y-%m-%d') AS D
FROM air_vault
WHERE CURRENT_DATE = date_format(from_unixtime(d_utime),'%Y-%m-%d')
GROUP BY H

I would suggest doing:
SELECT COUNT(distinct db_suid),
date_format(from_unixtime(d_utime),'%H') AS H,
date_format(from_unixtime(d_utime),'%Y-%m-%d') AS D
FROM air_vault av
WHERE d_utime >= unix_timestamp(curdate()) and
d_utime < unix_timetamp(curdate() + interval 1 day)
GROUP BY H, D;
Why is the logic phrased this way? The conditions in the where clause can use an index on d_utime if it is available -- or partitions if the data is partitioned on that column. That can significantly increase the performance of the query.
When a column is the argument to a function (such as from_unixtime()), indexes are almost never used.

manged my issue by modifying my WHERE condition:
WHERE CURRENT_DATE = date_format(from_unixtime(d_utime),'%Y-%m-%d')

Related

conditionally sum from one table based on information from another table

I am trying to write an sql query that outputs data for a python script. The python script will eventually push that data to a table so to make things smoother, I decided to cast the output as char.
The data that I have is organized by 15min periods. Data A and data B are stored on one table and have columns start_time (as a datetime), counts A, and counts B. The second table has start_time (as a datetime), and counts C.
What I need is sum for A, B, and C for each day. However, I want to sum conditionally where it only counts in the sum where the other two data counts are not NULL for that 15 min period. For example, if a "row" for a 15 min period has data for A and B but not C, it would not count in the sum. How do I implement this conditional?
example output:
date| SUM(A) | SUM(B) | SUM(C)
I can write without the conditional like this (new to sql):
SELECT
DATE('timezone conversion') AS date,
cast(SUM(p1.COUNT_DATA_A) as char)
AS A,
cast(SUM(p1.COUNT_DATA_B) as char)
AS B,
cast(SUM(p2.COUNT_DATA_C) as char)
AS C
FROM
table_data_A_B
AS p1
LEFT JOIN table_data_C
AS p2 ON p1.start_time = p2.start_time
WHERE
DATE('timezone conversion') >= '2018-03-27'
AND DATE('timezone conversion') < '2018-03-29'
GROUP BY DATE('timezone conversion')
ORDER BY DATE(p1.start_time) DESC
How would I implement the conditional in this query? I appreciate the help. I am a bit new to stackoverflow, coding and sql in general but I will try my best to be helpful.
Just test for this in the WHERE clause of the query.
WHERE DATE('timezone conversion') BETWEEN '2018-03-27' AND '2018-03-29'
AND p1.COUNT_DATA_A IS NOT NULL AND p1.COUNT_DATA_B IS NOT NULL AND p2.COUNT_DATA_C IS NOT NULL

MYSQL updating a table containing a join and subquery

I am relatively new to SQL, i am trying to update monthly salary based on employees working for a certain duration, the query displays the data using info from the person and employee table but it won't update, i keep getting a 'operand should contain 1 column' error? How would i go about displaying all the data and be able to update the monthly_salary column as well? Thanks.
UPDATE employee ep set monthly_salary = monthly_salary*1.15 = all(
SELECT p.person_id, p.name_first, p.name_last, ep.monthly_salary, ep.start_date, curdate() as today_date,
TIMESTAMPDIFF(month,ep.start_date,curdate()) as duration_months
FROM employee ep
INNER JOIN person p ON ep.person_id = p.person_id having duration_months > 24);
query result
I want this expected result but the monthly salary hasn't been updated yet, is it possible to display this and update the monthly_salary?
You are not able to do both in a single query. Typically one would run a "select query" to inspect if the desired logic appears correct, e.g.
SELECT
p.person_id
, p.name_first
, p.name_last
, ep.start_date
, curdate() as today_date
, TIMESTAMPDIFF(month,ep.start_date,curdate()) as duration_months
FROM employee ep
INNER JOIN person p ON ep.person_id = p.person_id
WHERE ep.start_date < curdate() - INTERVAL 24 MONTH
;
In that query the important piece of logic is the where clause which seeks out any employees with a start date earlier than today - 24 months.
If that logic is correct, then apply the same logic in an "update query":
UPDATE employee ep
SET monthly_salary = monthly_salary*1.15
WHERE ep.start_date < curdate() - INTERVAL 24 MONTH
;
Syntax notes:
you cannot string multiple conditions together using multiple equality operators (monthly_salary = monthly_salary*1.15 = all(...) there are 2 = signs in that
x = all() requires that all values returned by a subquery will equal x
the having clause is NOT just a substitute for a where clause. A having clause is designed for evaluating aggregated data e.g. having count(*) > 2
Finally, while it was inventive to use the having clause, what you were doing was gaining access to the alias 'duration_months', so you could simply have done this instead:
where TIMESTAMPDIFF(month,ep.start_date,curdate()) > 24
BUT this is not a good way to filter information because it requires running a function on every row of data before a decision can be reached. This has he effect of making queries slower. Compare that to the following:
WHERE ep.start_date < curdate() - INTERVAL 24 MONTH
ep.start_date is not affected by any function, and curdate() - INTERVAL 24 MONTH is just one calculation (not done every row). So this is much more efficient (also known as "sargable").

MYSQL SUM of Month to Date Sum Grouped By Day

Trying to calculate month to date revenue entered into the system for every day of the year by market. Current query works but it keeps timing out within my BI tool's mysql instance (set to 15 min). My BI tool may also not allow for mysql variables and if they do it would have to be conditional. I would ideally like to add more conditions.
/* Current query with subquery, this works syntactically, but is inefficient*/
SELECT
d.`Event Date`,
d.`market`,
(SELECT SUM(s.`Revenue`)
FROM time_from_start s
WHERE s.`created` <= d.`Event Date`
AND s.`Month/Year` = d.`Month/Year`
AND s.`market` = d.`market`) as 'Revenue to Date'
FROM time_from_start d
GROUP BY d.`Event Date`,d.market
Try using a query that avoids the use of a correlated subquery by using a self join instead.
This query should give the same results as your original query:
SELECT d1.`Event Date`, d1.market, SUM(d2.Revenue) AS Revenue_to_date
FROM time_from_start d1
LEFT JOIN time_from_start d2
ON d2.market = d1.market
AND d2.`Month/Year` = d1.`Month/Year`
AND d2.created <= d1.`Event Date`
GROUP BY d1.`Event Date`, d1.market
Also, make sure that there are indexes on the columns used in the query.

My join sql query won't bring results

What could be wrong with my sql query here , I'd like to retrieve data from both tables meeting a WHERE condition
SELECT *, UNIX_TIMESTAMP(i.sent_date) AS udate
FROM ibc_sent_history as i INNER JOIN
ibc_messages as u
ON i.msg_ids = u.id
WHERE (i.sent_date >= '02-02-2013' AND i.sent_date <= '02-02-2014')
ORDER BY i.sent_date
LIMIT 200
Assuming your ibc_sent_history.sent_date datatype is DATETIME, here's a way to refactor this query. (This will work even if the datatype is DATE). You need to change your date input string format from 02-02-2013 to the more standard '2014-02-02` (YYYY-MM-DD).
SELECT whatever, whatever
FROM ibc_sent_history AS i
INNER JOIN ibc_messages AS u ON i.msg_ids = u.id
WHERE i.sent_date >= '2013-02-02'
AND i.sent_date < '2014-02-02' + INTERVAL 1 DAY
ORDER BY i.sent_date DESC
LIMIT 200
I changed the ORDER BY to include DESC. This is to return the most recent items, not the oldest. If that's not what you need, take off the DESC.
I changed the date formatting.
I changed the end of your selection range to
i.sent_date < '2014-02-02` + INTERVAL 1 DAY
That's because
i.sent_date <= '2014-02-02`
will include items that occur precisely at midnight on 2-Feb-2014, but won't include any other items on that day. What you probably want are items that occurred up to but NOT including midnight on the next day.
I don't know MySQL very well, but in SQL Fiddle when I run:
CAST('2014-02-02' AS DATE)
I get a date, when I run
CAST('02-02-2014' AS DATE)
I get NULL, so seems like your date format is wrong.
Demo: SQL Fiddle

Mysql summary query with date range, multiple tables

Im running a sql query that is returning results between dates I have selected (2012-07-01 - 2012-08-01). I can tell from the values they are wrong though.
Im confused cause its not telling me I have a syntax error but the values returned are wrong.
The dates in my database are stored in the date column in the format YYYY-mm-dd.
SELECT `jockeys`.`JockeyInitials` AS `Initials`, `jockeys`.`JockeySurName` AS Lastname`,
COUNT(`runs`.`JockeysID`) AS 'Rides',
COUNT(CASE
WHEN `runs`.`Finish` = 1 THEN 1
ELSE NULL
END
) AS `Wins`,
SUM(`runs`.`StakeWon`) AS 'Winnings'
FROM runs
INNER JOIN jockeys ON runs.JockeysID = jockeys.JockeysID
INNER JOIN races ON runs.RacesID = races.RacesID
WHERE `races`.`RaceDate` >= STR_TO_DATE('2012,07,01', '%Y,%m,%d')
AND `races`.`RaceDate` <= STR_TO_DATE('2012,08,01', '%Y,%m,%d')
GROUP BY `jockeys`.`JockeySurName`
ORDER BY `Wins` DESC`
It's hard to guess what the problem is from your question.
Are you looking to summarize all the races in July and the races on the first of August? That's a slightly strange date range.
You should try the following kind of date-range selection if you want to be more precise. You MUST use it if your races.RaceDate column is a DATETIME expression.
WHERE `races`.`RaceDate` >= STR_TO_DATE('2012,07,01', '%Y,%m,%d')
AND `races`.`RaceDate` < STR_TO_DATE('2012,08,01', '%Y,%m,%d') + INTERVAL 1 DAY
This will pick up the July races and the races at any time on the first of August.
But, it's possible you're looking for just the July races. In that case you might try:
WHERE `races`.`RaceDate` >= STR_TO_DATE('2012,07,01', '%Y,%m,%d')
AND `races`.`RaceDate` < STR_TO_DATE('2012,07,01', '%Y,%m,%d') + INTERVAL 1 MONTH
That will pick up everything from midnight July 1, inclusive, to midnight August 1 exclusive.
Also, you're not using GROUP BY correctly. When you summarize, every column in your result set must either be a summary (SUM() or COUNT() or some other aggregate function) or mentioned in your GROUP BY clause. Some DBMSs enforce this. MySQL just rolls with it and gives strange results. Try this expression.
GROUP BY `jockeys`.`JockeyInitials`,`jockeys`.`JockeySurName`
My best guess is that the jocky surnames are not unique. Try changing the group by expression to:
group by `jockeys`.`JockeyInitials`, `jockeys`.`JockeySurName`
In general, it is bad practice to include columns in the SELECT clause of an aggregation query that are not included in the GROUP BY line. You can do this in MySQL (but not in other databases), because of a (mis)feature called Hidden Columns.