IF condition along with WHERE NOT EXISTS mysql - mysql

Below is my query :
SELECT *
FROM A WHERE NOT EXISTS
(SELECT *
FROM B
WHERE A.ItemCode = B.ItemCode AND A.Store = B.StoreName GROUP BY B.ItemCode,B.StoreName) AND A.Store='Food Store'
I wish to add a condition if B.Date <= '2014-05-10' then only the above query should work.
Suppose:-
A Table: 10 records, B Table: 5 records of today and 3 records of yesterday are present. if yesterday's date is selected, the output should be 7 records from Table A and if today's date is selected then 2 records from Table A should be found(5+3) and if day-before yesterday is selected then all records from Table A should be found.
Kindly help me.

U can simply add it at the end if i'm not mistaken
SELECT * FROM A WHERE NOT EXISTS (SELECT * FROM B WHERE A.ItemCode = B.ItemCode AND A.Store = B.StoreName GROUP BY B.ItemCode,B.StoreName) AND A.Store='Food Store' AND B.Date < '2014-05-10'

You need to add the condition in the part of the query where B is known. That is in the subquery:
SELECT *
FROM A
WHERE NOT EXISTS (SELECT 1
FROM B
WHERE A.ItemCode = B.ItemCode AND
A.Store = B.StoreName AND
B.Date <= '2014-05-10'
) AND
A.Store = 'Food Store';
Note that you do not need the group by in the subquery. You don't care how many or which rows exist, just whether any meet those conditions. I also replaced the * by 1. With the group by, the * is misleading because it has no aggregation functions. I usually use 1 for exists clauses.

Related

Combining 2 MySQL Queries from Different Databases

I've been trying my hand at this and I just keep getting an error or a query that hangs. Basically I have two database queries (one from each database) and I need to combine the results of the first into the second but also use the ID of the second query in the first...confusing!
The first is a simple query. Getting the number of topics approved and set it as "commentnumber". As you can see in the WHERE clause: It needs to use a.ID which would be from the second query.
Database 1
(SELECT (t.topic_posts_approved - 1)
FROM forum.bb_topics t, forum.bb_xpost xp
WHERE xp.wp_id = a.ID
AND t.topic_id = xp.topic_id) as 'commentnumber'
This is a query I've created to get 3 wordpress posts and sort them by a "weight". If I remove "commentnumber" (from the first query) it'll obviously work.
Database 2
SELECT a.post_author, a.id, b.pageviews, a.post_title, a.guid, c.meta_value, (b.pageviews * (c.meta_value + (commentnumber * 1.25))) AS 'weight'
FROM wordpress.wp_posts a, wordpress.wp_poppodyd b, wordpress.wp_postmeta c
WHERE a.ID = b.postid and (a.ID = c.post_id)
AND c.meta_key = 'thumbs_up'
AND (b.day >= NOW() - INTERVAL 2 DAY)
GROUP BY a.post_author
ORDER BY weight DESC
LIMIT 3
I've tried inner joining them but I either don't know what I'm doing or the query is just too much because a few variations I've tried just hangs until killed.
Any help would be massively appreciated!
I figured it out after sitting down for a couple of more hours with it.
As people have said, using the database.table.column name is the key.
Here is my end result in one query:
SELECT a.post_author, a.id, b.pageviews, a.post_title, a.guid, c.meta_value, t.topic_posts_approved, (b.pageviews * (c.meta_value + (t.topic_posts_approved * 1.25))) AS 'weight'
FROM wordpressdb.wp_posts a, wordpressdb.wp_poppodyd b, wordpressdb.wp_postmeta c, forumdb.bb_topics t, forumdb.bb_xpost xp
WHERE a.ID = b.postid and (a.ID = c.post_id) and (a.ID = xp.wp_id) and (t.topic_id = xp.topic_id)
AND c.meta_key = 'thumbs_up'
AND (b.day >= NOW() - INTERVAL 2 DAY)
GROUP BY a.post_author
ORDER BY weight DESC
LIMIT 3
I think you can create a new table and use both the database, select the columns that what you need and insert it to the new table then you can easily able to read that table.

MYSQL select max date from joined tables

I have 2 tables which I want to join and retrieve some specific data. These are my tables.
tbl_user (reg_id, l_name, f_name, status)
tbl_payments (pay_id, reg_id, mem_plan, from_date, to_date, bill_no, payed_date)
What I need to do is select and view the users who have due payments. To do that I want to get the user details where "status=0" from tbl_user and join the 2 tables together and the conditions are to_date< current date, difference between [current date and the to_date] < 31 and filter by the Max value of to_date.
What I did so far gives me a result according to above mentioned conditions except it dosen't filter by the MAX(to_date). This is my query.
SELECT
A.reg_id,
A.f_name,
A.l_name,
B.mem_plan,
B.from_date,
Max(B.to_date) AS to_date,
B.bill_no,
B.payed_date
FROM
tbl_user A,
tbl_payments B
WHERE
A.status = 0
AND A.reg_id = B.reg_id
AND Date(Now()) >= Date(B.to_date)
AND Datediff(Date(Now()), Date(b.to_date)) < 31
GROUP BY
a.reg_id, b.mem_plan, b.from_date, b.bill_no, b.payed_date;
I'm not very familiar with MYSQL, So please someone tell me what I did wrong or if this query is not up to the standard.
Here are some sample data to work on.
tbl_user ( [M1111,Jon, Doe,0], [M1112,Jane,Doe,1],[M1113,Jony,Doe,0] )
tbl_payment ( [1,M1111,Monthly,2018-05-14,2018-06-14,b123,2018-05-14],[2,M1112,3Months,2018-02-03,2018-05-03,b112,2018-02-03],[3,M1113,Monthly,2018-06-14,2018-07-14,b158,2018-06-14],[4,M1111,Monthly,2018-06-15,2018-07-15,b345,2018-06-15],[5,M1113,Monthly,2018-06-06,2018-07-06,b158,2018-06-06],[6,M1111,Monthly,2018-07-05,2018-08-05,b345,2018-07-05] )
Assuming current date is 2018-07-17, The expecting result should be this
[M1111,Jon,Doe,Monthly,2018-06-15,2018-07-15,b345,2018-06-15],[M1113,Jony,Doe,Monthly,2018-06-14,2018-07-14,b158,2018-06-14]
Instead of that, my query gives me this.
[M1111,Jon,Doe,Monthly,2018-06-15,2018-07-15,b345,2018-06-15],[M1113,Jony,Doe,Monthly,2018-06-06,2018-07-06,b158,2018-06-06],
[M1113,Jony,Doe,Monthly,2018-06-14,2018-07-14,b158,2018-06-14]
I wrote another query which gives me the result set exactly as i want. But I'm not sure whether it's up to the standards. If someone can simplify this or make it better, appreciate very much.
SELECT A.reg_id,A.f_name,A.l_name,D.mem_plan,D.from_date,D.to_date,D.bill_no,D.payed_date
FROM tbl_user A
JOIN (SELECT B.reg_id,B.mem_plan,B.from_date,B.to_date,B.bill_no,B.payed_date
FROM tbl_payments B
JOIN (
SELECT reg_id, MAX(to_date) as to_date
FROM tbl_payments
WHERE DATE(NOW()) >= DATE(to_date) AND DATEDIFF(DATE(NOW()), DATE(to_date))<31
GROUP BY reg_id) C
ON B.reg_id = C.reg_id AND B.to_date= C.to_date) D
ON A.reg_id = D.reg_id
WHERE A.status=0;
I believe having won't work here and that your second query is about as good as it gets. I've condensed it a little here:
SELECT A.reg_id,f_name,l_name,mem_plan,from_date,to_date,bill_no,payed_date
FROM #tbl_user A
JOIN #tbl_payments B ON A.reg_id = b.reg_id
JOIN (
SELECT reg_id, MAX(to_date) as max_to_date
FROM #tbl_payments
WHERE DATE(NOW()) >= DATE(to_date) AND DATEDIFF(DATE(NOW()), DATE(to_date))<31
GROUP BY reg_id
) C ON B.reg_id = C.reg_id AND B.to_date= C.max_to_date
WHERE A.status=0;

Select on aggregate result

I have a query which does a count from another table then adds a column for the result. I then need to alter the original select results based on that but am being told unknown column.
E.g. the following query does a count from another table within the main query, and the result is named shares, I need to filter the main query result set based on whether that column is greater than 0 but I get error unknown column shares
select b.name, event_title, ue.event_vis, event_date,
(select count(*) from list_shares
where user_id = 63 and event_id=ue.user_event_id) as shares,
(DAYOFYEAR(ue.event_date) - DAYOFYEAR(CURDATE())) as days
FROM brains b
join user_events ue on b.user_id=ue.user_id
where b.user_id=63 and ((ue.event_vis='Public') OR (shares>0))
and MOD(DAYOFYEAR(ue.event_date) - DAYOFYEAR(CURDATE()) + 365, 365) <= 30
order by days asc
Is there a way to do this?
I would suggest using a derived table to deliver the aggregate value and join it as you would do with a "phyiscal" table. Example:
select
b.name,
ue.event_title,
ue.event_vis,
ue.event_date,
tmp.shares,
(DAYOFYEAR(ue.event_date) - DAYOFYEAR(CURDATE())) as days
from
brains b join user_events ue on b.user_id = ue.user_id
left join (
select
ls.user_id,
ls.event_id,
count(*) as shares
from
list_shares ls
group by
ls.user_id,
ls.event_id) tmp on b.user_id = tmp.user_id and ue.user_event_id = tmp.event_id
where
b.user_id = 63
and
((ue.event_vis = 'Public') OR (tmp.shares > 0))
and
MOD(DAYOFYEAR(ue.event_date) - DAYOFYEAR(CURDATE()) + 365, 365) <= 30
order by
days asc
Please note the "left join". Because your using the OR operator in your where clause it seems to me like you want to get also rows without a share.
Of course you could also use the same subselect in your where clause but that's duplicate code and harder to maintain.
You cannot use a computed column to filter in the same query. Try something like
SELECT x.*
FROM (
/*Your Query*/
) as x
WHERE x.shares > 0
Or you could do something like
select b.name, event_title, ue.event_vis, event_date,
shares.SharesCount as shares,
(DAYOFYEAR(ue.event_date) - DAYOFYEAR(CURDATE())) as days
FROM brains b
join user_events ue on b.user_id=ue.user_id, event_id
JOIN (select count(*) as [sharesCount], from list_shares
where user_id = 63) as shares ON shares.event_id = ue.user_event_id
where b.user_id=63 and ((ue.event_vis='Public') OR (shares>0))
and MOD(DAYOFYEAR(ue.event_date) - DAYOFYEAR(CURDATE()) + 365, 365) <= 30
AND shares.sharesCount > 0
order by days asc

MS Access - Query design help

I need to design a query that finds "duplicates" in MS Access table. They are not true duplicates, in that every field is not identical, but it is highly unlikely that a patient would be seen twice within 60 days, so 2 records in that timespan are likely duplicates.
The relevant columns in the table are:
id integer autoincrement
patientid text
proceduredate date/time
I want to produce a list of patientid where the proceduredate is within 60 days of each other. I was able to find a list of all "duplicates" with the following query:
SELECT * FROM tblProcedures
WHERE patientid = ANY
(SELECT tblProcedures.patientid
FROM tblProcedures
GROUP BY tblProcedures.patientid
HAVING COUNT(tblProcedures.patientid) > 1)
ORDER BY tblProcedures.patientid, tblProcedures.proceduredate DESC
But I'm not sure how to limit the results to records involving the same patientid where the proceduredate is within 60 days of a previous procedure.
One solution is to join the table to itself:
Select *
From tblProcedures As P1
Inner Join tblProcedures As P2
On P2.PatientId = P1.PatientId
And P2.Id <> P1.Id
Where Abs(DateDiff("d", P1.ProcedureDate, P2.ProcedureDate)) <= 60
Order By P1.PatientId, P1.ProcedureDate Desc
I think you want something like:
SELECT *
FROM tblProcedures P1
LEFT JOIN tblProcedures P2
ON P1.patientid = P2.patientid
AND P1.proceduredate < P2.proceduredate
AND DateDiff("d", P1.proceduredate, P2.Proceduredate) <= 60
WHERE P2.patientid IS NOT NULL
ORDER BY P1.patientid, P1.proceduredate DESC

Subquery Comparison not returning results

I have two tables, one a schedule the other a list of available appointments for specific timeblocks. I take the times for a day of the week based on a date (First query)
select * from store_schedule where schedule_day = DATE_FORMAT('2011-01-17', '%a')
The above works fine.
I have a second query where I get the total amount of appointments for a date and specific time
SELECT count(*) from store_appointment a, store_schedule b
where a.store_schedule_id = b.id and apt_date = '2011-01-17'
In my case now I have two appointments at the same time on 2011/01/17 which is accurately returned using the above.
I have a column called concurrent_times in my store_schedule to determine how many appointments can share the same store_schedule_id in store_appointment. Below is my combined query.
select * from store_schedule where
schedule_day = DATE_FORMAT('2011-01-17', '%a') AND
(SELECT count(*) from store_appointment a, store_schedule b
where a.store_schedule_id = b.id
and apt_date = '2011-01-17') < concurrent_appointments
This query returns ZERO results for some reason. Can anyone see what I am doing wrong? Each query broken down works fine.
I'm an idiot :(. I misread my own queries. I don't need a second link to store_schedule.
Below is the correct query
select *
from store_schedule aa
where schedule_day = DATE_FORMAT('2011-01-17', '%a')
and ((select count(a.id) as countTotal
from store_appointment a
where a.store_schedule_id = aa.id
and apt_date = '2011-01-17') + 0) < concurrent_appointments