using multiple where cause in mysql - mysql

I have a table where I want to retreive data every hourly from database in report format.
like
username 8-9 9-10 10-11
====================================
kiran 20 27 33
Ram 25 23 44
Can we get like this in mysql please help.
select username,count(message) as '8-9' from customer_1.audit_trail
inner join inteliviz.users
on customer_1.audit_trail.user_id = inteliviz.users.id inner join
customer_1.carparks on customer_1.carparks.id = customer_1.audit_trail.location_id
where datetime>'2013-08-27 08:00:00' and datetime<'2013-08-27 09:00:00'
group by username limit 1000;

I think you are looking for conditional aggregation:
select username,
sum(datetime >= '2013-08-27 08:00:00' and datetime < '2013-08-27 09:00:00') as "8-9",
sum(datetime >= '2013-09-27 08:00:00' and datetime < '2013-08-27 10:00:00') as "9-10",
sum(datetime >= '2013-08-27 10:00:00' and datetime < '2013-08-27 11:00:00') as "10-11"
from customer_1.audit_trail t inner join
inteliviz.users u
on t.user_id = 8.id inner join
customer_1.carparks cp
on cp.id = t.location_id
group by username
limit 1000;
I also added table aliases to make the query easier to read. And, I changed the single quotes in column aliases to double quotes. It is a good idea to stick to using single quotes for strings and double quotes for aliases (which is consistent with the standard).

try using >= and <=
select username,count(message) as '8-9' from customer_1.audit_trail
inner join inteliviz.users on customer_1.audit_trail.user_id = inteliviz.users.id
inner join customer_1.carparks on customer_1.carparks.id = customer_1.audit_trail.location_id
where datetime>='2013-08-27 08:00:00' and datetime<='2013-08-27 09:00:00'
group by username limit 1000;
your current one looks between 01 and 59
edit:
http://www.artfulsoftware.com/infotree/queries.php#78
you want to be doing something like that and then grouping by hour(datetime)

Related

Identifying Duplicate Transactions in SQL

Recently because of an issue, multiple duplicate transactions were inserted into the database at different timings. Need to find those duplicate transactions and remove them.
I tried grouping the members and transactions
select count(*),
member_id,
TRUNC(created, 'DDD')
from TXN
where created > TO_DATE('06/01/2019 00:00:00', 'MM/DD/YYYY HH24:MI:SS')
group by member_id,
TRUNC(created, 'DDD')
having count(*) > 2;
I need all the transactions that were created in 10 minutes of time difference for the same member.
Examples:
MEMBER_ID ROW_ID ORG DEST Created
1-FRGD 1-FGTH YFG DFG 10-01-2019 00:00:00:00
1-FRGD 1-TYHG THU SEF 10-01-2019 00:00:09:12
1-FGHR 1-FTGH TGH DRF 10-01-2019 00:01:03:25
In this example, I need the first two txns as output because of not more than 10minutes if time difference and has the same member number
You may want self join:
select a.Member_Id as Member_Id,
a.Row_Id as Row_Id,
a.Org as Org,
a.Dest as Dest ,
a.Created as Created,
b.Row_Id as Duplicate_Row_Id,
b.Org as Duplicate_Org,
b.Dest as Duplicate_Dest,
b.Created as Duplicate_Created
from TXN a inner join
TXN b on a.Member_Id = b.Member_Id and
a.Created < b.Created and
TIMESTAMPDIFF(a.Created, b.Created) / 60 <= 10
order by a.Member_Id
For each record in TNX you provide its duplicate(s).
If you want to delete these transactions:
delete tnext
from txn tnext join
txn t
on tnext.member_id = t.member_id and
tnext.created > t.created and
tnext.created < t.created + interval 10 minute
where t.created > '2019-06-01';
Be sure you backup the table and test the logic using select before running this on your actual table.
If you simply want to select transactions without the duplicates, I would recommend not exists:
select t.*
from txn t
where not exists (select 1
from t tprev
where tprev.member_id = t.member_id and
tprev.created < t.created and
tprev.created > t.created - interval 10 minute
) and
t.created >= '2019-06-01';

How to get latest results by date when selecting from two table?

I have two tables and I would like to join then with a query.
result save the actual entry of results
user_tracking tracks the acceptance and completion of work, users can cancel and accepts work again at a later time.
SELECT *
from
svr1.result r,
svr1.user_tracking u
where
r.uid = u.user_id and r.tid = u.post1
and u.function_name = '7' #7 == accept work
and r.insert_time > '2015-09-23 00:00:00' and r.insert_time < '2015-10-03 00:00:00'
and u.track_time > '2015-09-23 00:00:00' and u.track_time < '2015-10-03 00:00:00'
my result table had 1785 records within the period I wanted to track
but the above query returns 1990 records. I would like to know how can i filter to get the latest date accepted by user only.
in result table: uid,INT, tid,INT, result,VARCHAR and insert_time,TIMESTAMP
in user_tracking table: user_id,INT, post1,VARCHAR function_name,VARCHAR, result,VARCHAR and track_time,TIMESTAMP
the user_tracking function sample records, in this query the track time will change and the rest will remain the same.
Use the GROUP BY command with a MAX() on the required date, this will select the latest date of all the options (assuming all the other columns are equal). Code as follows (need to declare all columns because of the MAX unfortunately):
SELECT r.uid,
r.tid,
r.result,
r.insert_time,
u.user_id,
u.post1,
u.function_name,
u.result,
MAX(track_time)
FROM
svr1.result r,
svr1.user_tracking u
WHERE
r.uid = u.user_id AND r.tid = u.post1
AND u.function_name = '7' #7 == accept work
AND r.insert_time > '2015-09-23 00:00:00' AND r.insert_time < '2015-10-03 00:00:00'
AND u.track_time > '2015-09-23 00:00:00' AND u.track_time < '2015-10-03 00:00:00'
GROUP BY
r.uid,
r.tid

Select the first element in each day of the month

How to select the first element of each day in a month with mysql query ?
I have table with offers - startdate, so i can check for each day,month,year i'm getting the element but, i'm wondering how to get only the first element in each day of some month ?
Assume the following
Table is called mytable
Table has id as primary key
Table has dt as datatime
You want the first id of everyday in February 2012
Try this:
SELECT B.id FROM
(
SELECT DATE(dt) date_dt,MIN(dt) dt
FROM mytable
WHERE dt >= '2012-02-01 00:00:00'
AND dt < '2012-03-01 00:00:00'
GROUP BY DATE(dt)
) A
LEFT JOIN mytable B USING (dt);
If any dt has multiple B.id values try this:
SELECT dt,MIN(id) id
(
SELECT B.id,B.dt FROM
(
SELECT DATE(dt) date_dt,MIN(dt) dt
FROM mytable
WHERE dt >= '2012-02-01 00:00:00'
AND dt < '2012-03-01 00:00:00'
GROUP BY DATE(dt)
) A
LEFT JOIN mytable B USING (dt)
) AA GROUP BY dt;
Assuming startdate is a DATETIME type, and the earliest entry is the one with the earliest DATETIME value, for March, 2012:
SELECT DISTINCT *
FROM tbl t1
LEFT JOIN tbl t2
ON (t2.startdate BETWEEN '2012-02-01 00:00:00' AND '2012-02-29 23:59:59')
AND t2.startdate < t1.startdate
WHERE (t1.startdate BETWEEN '2012-02-01 00:00:00' AND '2012-02-29 23:59:59')
AND t2.startdate IS NULL
If there are no duplicate dates, then you don't need the DISTINCT.
This query works by joining with any earlier record for the same month, so if nothing was joined, it's the earliest, through process of elimination.
This technique is explained in detail in the book SQL Antipatterns.
This could also be solved with subqueries, but this type of JOIN is supposed to be easier to optimize by MySQL than subqueries, which often negate the use of indexes.
without knowing the exact structure of your table something like this should work:
SELECT MIN(offerId) FROM offers WHERE startdate <= '2012-03-06' AND startdate >= '2012-02-06' GROUP BY date(startdate)
It sounds like you are trying to do something like the following:
SELECT col_1, date_col, col_3 FROM tbl
WHERE
date_col = ( SELECT min(date_col) FROM tbl
WHERE
year(date_col) = 2006 AND
month(date_col) = 02
);
This can also be used to find the max( date_col ) . Hope this helps.
Just to offer a different way to skin this cat (much easier in SQL Server for once actually)
SELECT
t0.offerId
FROM
offers AS t0 LEFT JOIN
offers AS t1 ON t0.offerId = t1.offerId AND t1.startDate > t0.startDate AND
(t0.startDate BETWEEN '2012-02-01' AND '2012-03-01') AND
(t1.startDate BETWEEN '2012-02-01' AND '2012-03-01')
WHERE
t1.col1 IS NULL;
If you have multiple rows with the same exact time you will get multiple values returned, which you can weed out in your application logic or with a sub-query. BTW this is called a groupwise minimum/maximum.

Trying to correct a mysql query

I currently have the following query;
SELECT a.schedID,
a.start AS eventDate, b.div_id AS divisionID, b.div_name AS divisionName
FROM schedules a
INNER JOIN divisions b ON b.div_id = a.div_id
WHERE date_format(a.start, '%Y-%m-%d') >= '2010-01-01'
AND DATE_ADD(a.start, INTERVAL 5 DAY) <= CURDATE()
AND NOT EXISTS (SELECT results_id FROM results e WHERE e.schedID = a.schedID)
ORDER BY eventDate ASC;
Im trying to basically find any schedules that do not have any results 5 days after the schedule date. My current query has major performance issues. It also times out inconsistently. Is there a different way to write the query? Im at a mental roadblock. Any help is appreciated.
Without antcipating much on the outcome I would suggest the following leads :
* try to remove the date_format as this generates one function call per record. I don't know the format of your column a.start but this should be possible.
* same for DATE_ADD, you could probably put it on the other member like :
a.start <= DATE_SUB(CURDATE(), INTERVAL 5 DAYS)
you get a chance the result is cached rather than being calculated for each line, you could even define it as a parameter upfront
* the NOT EXISTS is very expensive, it seems to mee you could replace this by a left join like :
schedules a LEFT JOIN results e ON a.schedId = e.schedId WHERE e.schedId is NULL
double-check that all join fields are well indexed.
Good luck
Maybe something like:
SELECT
a.schedID, a.start AS eventDate, b.div_id AS divisionID, b.div_name AS divisionName
FROM
schedules a
INNER JOIN divisions b ON b.div_id = a.div_id
WHERE
date_format(a.start, '%Y-%m-%d') >= '2010-01-01'
AND NOT EXISTS (
SELECT
*
FROM
results e
INNER JOIN schedules a2 ON e.schedID = a2.schedID
WHERE
DATE_ADD(a2.start, INTERVAL 5 DAY) <= CURDATE()
AND a2.id = a.id
)
ORDER BY eventDate ASC;
dont know if mysql is same as oracle but are you converting a date to a string here and then comparing it with a string '2010-01-01' ? Can you convvert 2010-01-01 to a date instead so that if there is an index on a.start, it can be used ?
Also does this query definitely return the right answer ?
You mention you want schedules without results 5 days after the schedule date but it looks like you are aksing for anything in the last 5 days ?
a.start >= 1-Jan-10 and start date + 5 days is before today
try this query
SELECT a.schedID,
a.start AS eventDate,
b.div_id AS divisionID,
b.div_name AS divisionName
FROM (SELECT * FROM schedules s WHERE DATE(s.start) >= '2010-01-01' AND DATE_ADD(s.start, INTERVAL 5 DAY) <= CURDATE()) a
INNER JOIN divisions b
ON b.div_id = a.div_id
LEFT JOIN (SELECT results_id FROM results) e
ON e.schedID = a.schedID
WHERE e.results_id = ''
ORDER BY eventDate ASC;

Looking to select a row from the database using DATETIME

I have the following query
SELECT * FROM ".TBL_FOOT_GAMES." ORDER BY id DESC LIMIT 1
I need to add a WHERE clause on the field date_confirmed.
date_confirmed is a DATETIME type.
I need to select only rows that are within 7 days of the current moment.
MORE CODE
SELECT g.home_user, g.away_user, g.home_score, g.away_score, g.id AS gameid, g.date_confirmed,
hu.username AS home_username, au.username AS away_username, ht.team AS home_team, at.team AS away_team
FROM tbl_foot_games g INNER JOIN tbl_users hu ON hu.id = g.home_user INNER JOIN tbl_users au ON au.id = g.away_user
INNER JOIN tbl_foot_teams ht ON ht.id = g.home_team INNER JOIN tbl_foot_teams at ON at.id = g.away_team
WHERE (g.type = '1' OR g.type = '2' OR g.type = '3' OR g.type = '4') AND g.status = '3' AND g.date_confirmed BETWEEN NOW() AND DATE_SUB(NOW(), INTERVAL 50 WEEK)
ORDER BY g.id DESC LIMIT 1
The statement works fine until I add the WHERE clause for the 50 week interval.
Presuming only seven days in the future (it looks like you're going to list upcoming football games):
SELECT *
FROM `tbl`
WHERE `date_confirmed` BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 1 WEEK)
ORDER BY `id` DESC
LIMIT 1
Please read the documentation first next time; the answers are all there.
... WHERE date_confirmed BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 7 DAY) ...
Have a look at the NOW() and DATE_SUB() functions.
These should let you create a date 7 days ago, then in your where clause you can check that the datetime column is greater than this.
You can use the date_sub function of MySQL to see if the diff is 7 days or less.
SELECT * FROM ".TBL_FOOT_GAMES."
WHERE DATE_ADD(DATE_CONFIRMED, INTERVAL '7 00:00:00' DAYS_SECOND) >= TIMESTAMP(CURDATE())
ORDER BY id DESC LIMIT 1
If you are interested in seeing only 7 days of difference from current date (ignoring the time value), then you can use DATEDIFF function like this:
SELECT * FROM ".TBL_FOOT_GAMES."
WHERE DATEDIFF(CURDATE(), DATE_CONFIRMED) <= 7
ORDER BY id DESC LIMIT 1