So i'm trying to select unread messages with a query, but the results are blank. I need to get the info from a seperate table read so it will know it was read or not. Im trying to do something like a IF statement so if readed not exists it will be unread, but i can't get it fixed
this is my query:
SELECT * FROM notify
INNER JOIN readed ON readed.acc_ID = '26' AND readed.user_ID = '6'
AND readed.msg_ID = notify.ID AND readed.readed != '1' OR readed.ID IS NULL
WHERE notify.groep = '1'
DB - readed
ID - int
user_ID - int
acc_ID - int
msg_ID - int
readed - enum ('0','1')
DB - notify
ID - int
notfi - text
thumb_src - text
title - text
url - text
groep - int
I hope someone know whats the problem!
The query seems correct to me, except the part with the OR, so I suppose that the problem is with the data. I will first try to show how you could improve the query nevertheless, and then try to show how to debug your data.
First, let's leave away the OR condition since this won't work as expected in a JOIN ON clause.
Second, when comparing integer fields to values, you should not put quotes around the values. This will only worry every person who tries to understand the query because the quotes denote string values, and it will worry (i.e. slow down) MySQL's parser, because it must convert the string values to numbers.
Third, mixing up normal WHERE conditions and JOIN ON conditions is worrying and bad style (IMHO). I always recommend to put only the conditions which actually link the tables into the JOIN ON clause, and other conditions elsewhere.
Following this advice would lead to something like that:
SELECT * FROM
notify INNER JOIN readed ON
readed.msg_ID = notify.ID
WHERE
readed.acc_ID = 26 AND
readed.user_ID = 6 AND
readed.readed != '1' AND
notify.groep = 1
This should do the same as your original query minus the OR part.
Now, since we suspect that there is a problem with the data, we can begin to debug the data. First, leave away the WHERE clause:
SELECT * FROM
notify INNER JOIN readed ON
readed.msg_ID = notify.ID
If this returns data, then you at least know that there are rows in the readed table matching rows in the notify table. If it does not return any data, then there are no rows which fit together, and have found the root of your problem.
Provided that the above returns data, re-add the WHERE clause line by line and test after each step. For example, start with
SELECT * FROM
notify INNER JOIN readed ON
readed.msg_ID = notify.ID
WHERE
readed.acc_ID = 26 AND
and continue with
SELECT * FROM
notify INNER JOIN readed ON
readed.msg_ID = notify.ID
WHERE
readed.acc_ID = 26 AND
readed.user_ID = 6 AND
and so on, testing the query each time.
That way, you hopefully will find out where the problem is. I am convinced that the problem is with the data, not with the query.
Related
I'm trying to inherit value from previous row (based on correct subscription_id + checking for IS NULL subscription_status), but something goes wrong and I get incorrect value.
Take a look at screenshot.
If I'm not mistaken it also called last non-null puzzle, but examples of possible solution for other DB provide window function with IGNORE NULLS.
But, I'm using MySQL 8.x and it doesn't support this function.
I'm sorry, but SQL fiddle doesn't provide correct text-value for variables in my code :(
https://www.db-fiddle.com/f/wHanqoSCHKJHus5u6BU4DB/4
Or, you can see mistakes here:
SET #history_subscription_status = NULL;
SET #history_subscription_id = 0;
SELECT
c.date,
c.user_id,
c.subscription_id,
sd.subscription_status,
(#history_subscription_id := c.subscription_id) as 'historical_sub_id',
(#history_subscription_status := CASE
WHEN #history_subscription_id = c.subscription_id AND sd.subscription_status IS NULL
THEN #history_subscription_status
ELSE
sd.subscription_status
END
) as 'historical'
FROM
calendar c
LEFT JOIN
subscription_data sd ON sd.date = c.date AND sd.user_id = c.user_id AND sd.subscription_id = c.subscription_id
ORDER BY
c.user_id,
c.subscription_id,
c.date
I expect to get results for this query in this way:
IMPORTANT: I'm going to use this code for a lot of data (about 1 mln rows), so it very important for me to avoid additional select or subquery that can slow down the execution of the query.
I am working on a query for a datatable and I can't seem to get it to display how I want, I don't know if this is even possible in SQL What I am looking to do is get a query to respond with ideally an extra column of Boolean type.
Currently I can run two queries and they both work perfectly but I can't work out how to join them together bellow is the code from my first query what this does is return beers a user has tried this works fine and as expected and returns as expected.
SELECT *
FROM keg.beer
JOIN keg.userbeer
ON beer.id = userbeer.beer_id
WHERE userbeer.username_id = 1;
The second query is even simpler and is just a select getting the list of beers.
SELECT * FROM keg.beer
What I want to do is run a query and have it return a list of beers with a Boolean value if the user has tried it or not.
You're not going to run into too many scenarios for "Desired Results" that can't be produced with plain 'ol SQL. In this case you'll use a CASE statement to determine if the person has tried a beer. You'll also want a LEFT OUTER JOIN so you don't drop records coming from your beer table when your filtered userid doesn't have a userbeer record for that beer:
SELECT
beer.name,
beer.id,
beer.country,
CASE WHEN userbeer.username_id IS NULL THEN 0 ELSE 1 END AS user_tried_beer_boolean
FROM keg.beer
LEFT OUTER JOIN keg.userbeer
ON beer.id = userbeer.beer_id
AND userbeer.username_id = 1;
As #SeanLange mentioned in the comments here, the restriction of the WHERE statement for the userid would cause records to be dropped that you want in your result set, so we move the restriction of username_id = 1 to the ON portion of the LEFT OUTER JOIN so that the userbeer table results are restricted to just that user before it's joined to the beer table.
Now I need a drink.
SELECT b.id,
b.name,
CASE WHEN u.username_id IS NOT NULL THEN TRUE ELSE FALSE END AS userdrankbeer
FROM keg.beer b
LEFT JOIN ( SELECT * FROM keg.userbeer WHERE username_id = 1 ) u
ON beer.id = userbeer.beer_id
;
I'm trying to write a MYSQL Query that updates a cell in table1 with information gathered from 2 other tables;
The gathering of data from the other 2 tables goes without much issues (it is slow, but that's because one of the 2 tables has 4601537 records in it.. (because all the rows for one report are split in a separate record, meaning that 1 report has more than 200 records)).
The Query that I use to Join the two tables together is:
# First Table, containing Report_ID's: RE
# Table that has to be updated: REGI
# Join Table: JT
SELECT JT.report_id as ReportID, REGI.Serienummer as SerialNo FROM Blancco_Registration.TrialTable as REGI
JOIN (SELECT RE.Value_string, RE.report_id
FROM Blancco_new.mc_report_Entry as RE
WHERE RE.path_id=92) AS JT ON JT.Value_string = REGI.Serienummer
WHERE REGI.HardwareType="PC" AND REGI.BlanccoReport=0 LIMIT 100
This returns 100 records (I limit it because the database is in use during work hours and I don't want to steal all resources).
However, I want to use these results in a Query that updates the REGI table (which it uses to select the 100 records in the first place).
However, I get the error that I cannot select from the table itself while updateing it (logically). So I tried selecting the select statement above into a temp table and than Update it; however, then I get the issue that I get to much results (logically! I only need 1 result and get 100) however, I'm getting stuck in my own thougts.. I ultimately need to fill the ReportID into each record of REGI.
I know it should be possible, but I'm no expert in MySQL.. is there anybody that can point me into the right direction?
Ps. fixing the table containing 400k records is not an option, it's a program from an external developer and I can only read that database.
The errors I'm talking about are as follows:
Error Code: 1093. You can't specify target table 'TrialTable' for update in FROM clause
When I use:
UPDATE TrialTable SET TrialTable.BlanccoReport =
(SELECT JT.report_id as ReportID, REGI.Serienummer as SerialNo FROM Blancco_Registration.TrialTable as REGI
JOIN (SELECT RE.Value_string, RE.report_id
FROM Blancco_new.mc_report_Entry as RE
WHERE RE.path_id=92) AS JT ON JT.Value_string = REGI.Serienummer
WHERE REGI.HardwareType="PC" AND REGI.BlanccoReport=0 LIMIT 100)
WHERE TrialTable.HardwareType="PC" AND TrialTable.BlanccoReport=0)
Then I tried:
UPDATE TrialTable SET TrialTable.BlanccoReport = (SELECT ReportID FROM (<<and the rest of the SQL>>> ) as x WHERE X.SerialNo = TrialTable.Serienummer)
but that gave me the following error:
Error Code: 1242. Subquery returns more than 1 row
Haveing the Query above with a LIMIT 1, gives everything the same result
Firstly, your query seems to be functionally identical to the following:
SELECT RE.report_id ReportID
, REGI.Serienummer SerialNo
FROM Blancco_Registration.TrialTable REGI
JOIN Blancco_new.mc_report_Entry RE
ON RE.Value_string = REGI.Serinummer
WHERE REGI.HardwareType = "PC"
AND REGI.BlanccoReport=0
AND RE.path_id=92
LIMIT 100
So, why not use that?
EDIT:
I still don't get it. I can't see what part of the problem the following fails to solve...
UPDATE TrialTable REGI
JOIN Blancco_new.mc_report_Entry RE
ON RE.Value_string = REGI.Serinummer
SET TrialTable.BlanccoReport = RE.report_id
WHERE REGI.HardwareType = "PC"
AND REGI.BlanccoReport=0
AND RE.path_id=92;
(This is not an answer, but maybe a pointer towards a few points that need further attention)
Your JT sub query looks suspicious to me:
(SELECT RE.Value_string, RE.report_id
FROM Blancco_new.mc_report_Entry as RE
WHERE RE.path_id=92
GROUP BY RE.report_id)
You use group by but don't actually use any aggregate functions. The column RE.Value_string should strictly be something like MAX(RE.Value_string) instead.
I have a search page that has multiple fields that are used to create a refined search. Every field is optional. I'm trying to start crafting my sql query so that it will work given the proper variables but I'm having trouble.
Here is the SQL query I currently have:
SELECT
indicator.indid,
indicator.indicator,
indtype.indtype,
provider.provider,
report.report,
actor.actor
FROM
actor,
indicator,
indtype,
report,
provider
WHERE
indicator.indtypeid = indtype.indtypeid
AND indicator.actorid = actor.actorid
AND indicator.reportid = report.reportid
AND report.providerid = provider.providerid
AND indicator.indicator LIKE '%$indicator%'
AND indicator.indtypeid = $indtypeid;
Whenever I provide an indicator and an indtypeid, the search works just fine. However, when I leave the indtypeid field blank, and have the variable set to * (as its default value), the query returns no results. I've tried playing with the query manually and it doesn't seem to like the * or a % sign. Basically, if only an indicator is specified and no indtypeid is specified, I want to return all indicators for all indtypeids.
I'm sure I'm missing something minor, but I would appreciate any assistance that could be provided. I may be going about this all wrong in the first place.
Try this instead:
SELECT i.indid, i.indicator, it.indtype,
p.provider, r.report, a.actor
FROM actor a
INNER JOIN indicator i ON a.actorid = i.actorid
INNER JOIN indtype it ON i.indtypeid = it.indtypeid
INNER JOIN report r ON i.reportid = r.reportid
INNER JOIN provider p ON r.providerid = p.providerid
WHERE 1 = 1
AND ($indicator IS NULL OR i.indicator LIKE '%$indicator%')
AND ($indtypeid IS NULL OR i.indtypeid = $indtypeid);
So if you pass a $indicator = NULL, then the first condition AND ($indicator IS NULL OR i.indicator LIKE '%$indicator%') will be ignored since it will resolve to True, and the same thing for the second condition.
I've removed other Where condition and replace them with JOINs, and for WHERE 1 = 1 to make the query work fine in case you pass the two variables $indicator and $indtypeid with NULL values for each, in this case it will return all results since 1 = 1 always true.
I've been trying to write a few little plugins for personal use with WHMCS. Essentially what I'm trying to do here is grab a bunch of information about a certain order(s), and return it as an array in Perl.
The Perl bit I'm fine with, it's the MySQL query I've formed that's giving me stress..
I know it's big and messy, but what I have is:
SELECT tblhosting.id, tblhosting.userid, tblhosting.orderid, tblhosting.packageid, tblhosting.server, tblhosting.domain, tblhosting.username, tblorders.invoiceid, tblproducts.gid, tblservers.ipaddress, tblinvoices.status
FROM tblhosting, tblproducts, tblorders, tblinvoices, tblservers
WHERE tblorders.status = 'Pending'
AND tblproducts.gid = '2'
AND tblservers.id = tblhosting.server
AND tblorders.id = tblhosting.orderid
AND tblinvoices.id = tblorders.invoiceid
AND tblinvoices.status = 'Paid'
I don't know if this /should/ work, but I assume I'm on the right track as it does return what I'm looking for, however it returns everything twice.
For example, I created a new account with the domain 'sunshineee.info', and then in PHPMyAdmin ran the above query.
id userid orderid packageid server domain username invoiceid gid ipaddress status
13 7 17 6 1 sunshineee.info sunshine 293 2 184.22.145.196 Paid
13 7 17 6 1 sunshineee.info sunshine 293 2 184.22.145.196 Paid
Could anyone give me a heads up on where I've gone wrong with this one.. Obvioiusly (maybe not obviously enough) I want this as only one row returned per match.. I've tried it with >1 domain in the database and it returned duplicates for each of the matches..
Any help would be much appreciated
:)
SELECT distinct tblhosting.id, tblhosting.userid, tblhosting.orderid, tblhosting.packageid, tblhosting.server, tblhosting.domain, tblhosting.username, tblorders.invoiceid, tblproducts.gid, tblservers.ipaddress, tblinvoices.status
FROM tblhosting, tblproducts, tblorders, tblinvoices, tblservers
WHERE tblorders.status = 'Pending'
AND tblproducts.gid = '2'
AND tblservers.id = tblhosting.server
AND tblorders.id = tblhosting.orderid
AND tblinvoices.id = tblorders.invoiceid
AND tblinvoices.status = 'Paid'
Well, its near impossible without any table definitions, but you are doing a lot of joins there. You are starting with tblhosting.id and working your way 'up' from there. If any of the connected tables has a double entry, you'll get more hits
You could add a DISTINCT to your query, but that would not fix the underlying issue. It could be a problem with your data: do you have 2 invoices? Maybe you should select everything (SELECT * FROM) and check what is returned, maybe check your tables for double content.
Using DISTINCT is most of the time not a good choice: it means either your query or your data is incorrect (or you don't understand them thoroughly). It might get you the right result for now, but can get you in trouble later.
A guess about the reason this happens:
You do not connect the products table to the chain of id's. So you are basically adding a '2' to your result as far as I can see. You join on products, and the only thing that limits that table is that "gid" should be 2. So if you add a product with gid 2 you get another result. Either join it (maybe tblproduct.orderid = tblorders.id ? just guessing here) or just remove it, as it does nothing as far as I can see.
If you want to make your query a bit clearer, try not implicitly joining, but do it like this. So you can actually see what's happening
SELECT tblhosting.id, tblhosting.userid, tblhosting.orderid, tblhosting.packageid, tblhosting.server, tblhosting.domain, tblhosting.username, tblorders.invoiceid, tblproducts.gid, tblservers.ipaddress, tblinvoices.status
FROM tblhosting
JOIN tblproducts ON /*you're missing something here!*/
JOIN tblorders ON tblorders.id = tblhosting.orderid
JOIN tblinvoices ON tblinvoices.id = tblorders.invoiceid
JOIN tblservers ON tblservers.id = tblhosting.server
WHERE
tblorders.status = 'Pending'
AND tblproducts.gid = '2'
AND tblinvoices.status = 'Paid'
I don't see in your query JOIN to tblproducts, it seems to be a reason.