I'm developing a search function for a website. I have a table called keywords with two fields id and keyword. I have two separate search queries for AND and OR. The problem is with the AND query. It is not returning the result that I expect.
The printed SQL is :
SELECT COUNT(DISTINCT tg_id)
FROM tg_keywords
WHERE tg_keyword='keyword_1'
AND tg_keyword='keyword_2'
The count returned is 0, while if I perform the same SQL with OR instead of AND the count returned is 1. I expected the count to be 1 in both cases, and I need it to be this way as the AND results will take priority over the OR results.
Any advice will be much appreciated.
Thanks
Archie
It will always return 0, unless keyword_1=keyword_2. tg_keyword can only have one value, and when you say AND, you're asking for both conditions to be true.
It's the same, logically speaking, as asking "How many friends do I have whose name is 'JACK' and 'JILL'"? None, nobody is called both JACK and JILL.
I don't know what your table looks like and how things are related to each other, but this query makes no sense. You're returning rows where the keyword is one thing and another thing at the same time? That's impossible.
You probably have another table that links to the keywords? You should search with that, using a join, and search for both keywords. We could give you a more precise answer if you could tell us what your tables look like.
EDIT: Based on what you wrote in a comment below (please edit your question!!), you're probably looking for this:
SELECT COUNT(DISTINCT tg_id)
FROM tg_keywords AS kw1, tg_keywords AS kw2
WHERE kw1.tg_id = kw2.tg_id
AND kw1.tg_keyword='keyword_1'
AND kw2.tg_keyword='keyword_2'
your query can't work because you have a condition which is always false so no record will be selected!
tg_keyword='keyword_1' AND tg_keyword='keyword_2'
what are you trying to do? Could you post the columns of this table?
tg_keyword='keyword_1' AND tg_keyword='keyword_2'
Logically this cannot be true, ever. It cannot be both. Did you mean something like:
SELECT * FROM keywords
WHERE tg_keyword LIKE '%keyword_1%' OR tg_keyword LIKE '%keyword_2%'
ORDER BY tg_keyword LIKE '%keyword_1%' + tg_keyword LIKE '%keyword_2%' DESC;
Based on the OP's clarification:
I have a table with multiple keywords with the same id. How can I get more than one keyword compared for the same id, as the search results need to be based on how many keywords from a search array match keywords in the keywords table from each unique id. Any ideas?
I assume you're looking to return search results based on a ranking of how many of the selected keywords are a match with those results? In other words, is the ID field that multiple keywords share the ID of a potential search result?
If so, assuming you pass in an array of keywords of the form {k1, k2, k3, k4}, you might use a query like this:
SELECT ID, COUNT(ID) AS ResultRank FROM tg_keywords WHERE tg_keyword IN (k1, k2, k3, k4) GROUP BY ID ORDER BY ResultRank DESC
This example also assumes a given keyword might appear in the tables multiple times with different IDs (because a keyword might apply to multiple search results). The query will return a list of IDs in descending order based on the number of times they appear with any of the selected keywords. In the given example, the highest rank for a given ID should be 4, meaning ALL keywords apply to the result with that ID...
I think you will need to join tg_keywords to itself. Try playing around with something like
select *
from tg_keywords k1
join tg_keywords k2 on k1.tg_id = k2.tg_id
where k1.tg_keyword = 'keyword_1' and k2.tg_keyword = 'keyword_2'
Try:
SELECT tg_id
FROM tg_keywords
WHERE tg_keyword in ('keyword_1','keyword_2')
GROUP BY tg_id
HAVING COUNT(DISTINCT tg_keyword) = 2
Related
This is quite difficult to explain in the title, so I'll do my best here. Basically I have a column in a MySQL products table that contains rows like:
FEL10
FEL20
FEL30
PRO05
PRO07
PRO08
VAI12
VAI13
VAI14
These are the categories ("FEL","PRO","VAI") and a identification number of my products ("10", "20" and so on). I need an SQL select query that creates me a textual array like:
FEL*
PRO*
VAI*
With this array I need to create a listbox, that allows me to choose a category (regardless of the identification number). Once I choose a category, let's say PRO*, I will need to do the reverse action: print all the products info related to PRO05, PRO07 and PRO08.
How do you think you can achieve this? I have been trying using the DISTINCT statement but I need to filter only the first characters, otherwise it will be useless. I also tried the SUBSTRING() and LEFT() functions, but they seem not to be working (I get an SQL Syntax error).
--
Thanks for your help as always
What is wrong with?
SELECT distinct left(col, 3) as category FROM `table1`
MySQL LIKE to the resque:
SELECT col1 FROM table1 WHERE col1 LIKE 'FEL%';
This way you have to add all cases using OR.
Alternative - REGEXP:
SELECT col1 FROM table1 WHERE col1 REGEXP '(FEL|PRO|VAI).*'
Then it's just a matter of writing proper regex.
I would use extra col to group your items - to avoid such selecting altogether (which should be quite expensive on bigger dataset).
https://dev.mysql.com/doc/refman/5.1/en/regexp.html#operator_regexp
To get the list of the 3-letter codes use:
select distinct left(combicode, 3)
from mytable;
When a user selects one of the values use this to get all matching entries:
select *
from mytable
where combicode like concat(#category, '%');
(Aside from that: It's a bad idea to have concatenated values in one column. Why not have one column for the category and another for the product code? Then there would be no problem at all.)
Yes, there's a thousand questions about this on SO, but I've been searching for half an hour and I've yet to find a solution.
So, I've a table like this:
And this is my query:
SELECT DISTINCT rengasID,leveys FROM renkaat ORDER BY leveys ASC
And this is the result I get:
If you get the idea, I'm populating a select field with it, but it still has duplicates.
What am I doing wrong?
If you want distinct leveys, just choose that field:
SELECT DISTINCT leveys
FROM renkaat
ORDER BY leveys ASC
The rengasid has a different value on each row.
The distinct clause applies to all the columns being returned, regardless of parentheses.
EDIT:
If you need the regasid in the result, then use group by:
select leveys, min(regasid) as regasid
from renkaat
group by leveys
order by leveys asc;
This gives the first id. If you need all of them, you can get them in a list using group_concat(). If you need a separate id on each row, well, then you have duplicates.
Your rengasID is still different in each shown line. The distinct will check a mix of every selected field, so in this case it will search a distinct combination of rengasID and leveys.
You cannot ask for your ID here, since MySQL has no way of knowing which one you want.
Depending on what you want to do it can be more correct to save your "leveys" (I'm not sure what they are) in a separate table with a unique ID and join it. For filling up your list with all possible leveys, you can just query that new table.
This can be important because using group by, you can get random results for id's later on.
This is because you are selecting combination of rengasID and leveys. And what you are getting as a result is a distinct combination of the two.
To achieve what you are trying, see the answer of #GordonLinoff.
I am currently working on a school system where we have a parent course and a child course (meta_courses in Moodle).
So, we have a table mdl_course_meta and it has 3 fields. Id, parent_course and child_course.
My problem is that a parent course can have many child courses so that means, for example, a parent_course = 50 can appear two times in the table which means it has 2 child courses. I just want to be able to find all the parent courses without it returning the same value twice or more times. I'm currently using this query right now which obviously doesn't do what I want:
$q = "SELECT * FROM mdl_course_meta";
I am working with PHP as well by the way.
Thanks a lot.
SELECT DISTINCT parent_course from mdl_course_meta
That should do it if you just want the course names. One thing to keep in mind, if you want other fields this is not going to work the way you want it to(how would it know which record to choose if there are multiple records with the same parent_course and you only want one).
This approach can only be used if you only want to return the parent_courses without duplicates.
DISTINCT helps to eliminate duplicates. If a query returns a result that contains duplicate rows, you can remove duplicates to produce a result set in which every row is unique. To do this, include the keyword DISTINCT after SELECT and before the output column list.
$q = "SELECT DISTINCT parent_course FROM mdl_course_meta";
If you don't want duplicate values in a single column, use GROUP BY parent_course.
In this way you are free to select any column.
If you only want distinct values for a particular column column, then you can use GROUP BY:
SELECT *
FROM mdl_course_meta
GROUP BY parent_course
The values in the other columns will be arbitrary. This will work in MySQL 5.x.
MySQL 4.x won't let you be arbitrary, so you can't mix aggregate and non-aggregate columns. Instead, you'd have to do something like this, which gets a bit complicated:
SELECT MAX(col1), MAX(col2), parent_course, MAX(col4), ...
FROM mdl_course_meta
GROUP BY parent_course
This way, the values aren't arbitrary. You've specified the ones you want.
I have two tables, for this example, I'm going to call them "content" and "likes".
"Content" contains multiple entries (each one like a famous quote or something of that nature).
The site allows users to click a like button and as such, an entry is inserted into the "likes" table with the corresponding ID from the "content" table so it can traced back.
I wish to write a query that sorts the content of the "content" table by the number of likes it has in the "likes" table - is that possible? If so, how?
Many thanks and happy holidays (the second part applies even if the problem remains unresolved)
Something like:
SELECT c.*
FROM Content c, Likes l
WHERE c.Content_Id = l.Content_Id
GROUP BY c.Content_Id
ORDER BY COUNT(*) DESC
Running a query like that every time you want to show the quotes ordered by the number of likes can become a bit intensive on the database. Have you considered adding a field to the quotes table that only keeps track of the number of likes?
That way, a query like this would suffice:
SELECT quote FROM content ORDER BY likes DESC;
It's somewhat creating redundancy, but not quite. Just an alternative to consider.
Yes it is possible to write a query like that.
SELECT count(*) as total, content.*
FROM content, likes
WHERE content.id = likes.id
GROUP BY total
ORDER BY total desc
I have a programme listing database with all the information needed for one programme packed into one table (I should have split programmes and episodes into their own) Now since there are multiple episodes for any given show I wish to display the main page with just the title names in ascending and chosen letter. Now I know how to do the basic query but this is all i know
SELECT DISTINCT title FROM programme_table WHERE title LIKE '$letter%'
I know that works i use it. But I am using a dynamic image loading that requires a series number to return that image full so how do I get the title to be distinct but also load the series number from that title?
I hope I have been clear.
Thanks for any help
Paul
You can substitute the DISTINCT keyword for a GROUP BY clause.
SELECT
title
, series_number
FROM
programme_table
WHERE title LIKE '$letter%'
GROUP BY
title
, series_number
There are currently two other valid options:
The option suggested by Mohammad is to use a HAVING clause in stead of the WHERE clause this is actually less optimal:
The WHERE clause is used to restrict records, and is also used by the query optimizer to determine which indexes and tables to use. HAVING is a "filter" on the final result set, and is applied after ORDER BY and GROUP BY, so MySQL cannot use it to optimize the query.
So HAVING is a lot less optimal and you should only use it when you cannot use 'WHERE' to get your results.
quosoo points out that the DISTINCT keyword is valid for all listed columns in the query. This is true, but generally people do not recommend it (there is no performance difference *In some specific cases there is a performance difference***)**. The MySQL optimizer however spits out the same query for both so there is no actual performance difference.
Update
Although MySQL does apply the same optimization to both queries, there is actually a difference: when DISTINCT is used in combination with a LIMIT clause, MySQL stops as soon as it finds enough unique rows. so
SELECT DISTINCT
title
, series_number
FROM
programme_table
WHERE
title LIKE '$letter%'
is actually the best option.
select title,series_number from programme_table group by title,series_number having title like '$letter%';
DISTINCT keyword works actually for a list of colums so if you just add the series to your query it should return a set of unique title, series combinations:
SELECT DISTINCT title, series FROM programme_table WHERE title LIKE '$letter%'
Hey thanks for that but i have about 1000 entries with the same series so it would single out the series as well rendering about 999 programmes useless and donot show.
I however found out away to make it unique and show the series number
SELECT * FROM four a INNER JOIN (SELECT title, MIN(series) AS MinPid FROM four WHERE title LIKE '$letter%' GROUP BY title) b ON a.title = b.title AND a.series = b.MinPid
Hopefully it helps anyone in the future and thank you for the replies :)