How to combine these two sql queries into one?
SELECT DISTINCT * FROM rss WHERE MATCH(content,title) AGAINST ('$filter')
SELECT COUNT(content) FROM rss WHERE MATCH(content,title) AGAINST ('$filters')
And if the result is 0 from the above query
-
SELECT DISTINCT * FROM rss WHERE content LIKE '%$filters%' OR title LIKE '%$filters%';
$filter .= $row['filter'];
$filters = $row['filter'];
$filters may be more than one keyword
You do not have to use query 2,
mysql_num_rows will indicate how many rows for query 1, so just discard query 2
if mysql_num_rows return zero, then proceed with query 3
To combine three queries into one, use OR
SELECT DISTINCT * FROM rss
WHERE
(MATCH(content,title) AGAINST ('$filter'))
OR
(content LIKE '%$filter%' OR title LIKE '%$filter%')
As explained above, you do not really need to do count first.
If $filter contains lots of keyword, then just repeating like
(content LIKE '%$filter_1%' OR title LIKE '%$filter_1%') OR
(content LIKE '%$filter_2%' OR title LIKE '%$filter_2%') OR ...
You can combine 1 and 3 using UNION ALL. But you can't merge 2nd with other 2, because COUNT returns aggregate for a bunch of rows.
You are better off writing a stored procedure in your case, than trying to stuff in all three into a single statement.
EDIT (via sv88erik): Since you are using UNION ALL, you don't need a DISTINCT keyword in each query.
Related
I have a situation where i need to get data from 7 different tables for a particular processing to be performed.
I will need 7 simple SELECT all statements, nothing fancy. But to minimize the database hit, I will very much like to bundle these queries into 1 or 2 queries.
Like:
select * from table1; select * from table2; select * from table3;.
And will call this query from my code. Is is possible to get the results in something on the similar lines of .net's DataSet in PHP. I am looking for a solution in core PHP or CodeIgniter. I am using PDO for database connection.
PS: The tables have different schemas, no common point. So any solution with join or union will not work.
$results = $this->db-query("select * from tb1; select * from tb2");
now $result[0] should have all the records from tb1 and $results[1] should have the records from tb2.
Something on the similar line will be most helpful in this scenario.
Look into InnerJoin. That's how you make multiple selections at once - assuming you have a common data point
What you need is UNION
$this->db->query('SELECT column_name(s) FROM table_name1 UNION ALL SELECT column_name(s) FROM table_name2');
UNION ALL This is the UNION keyword, and the optional ALL keyword. UNION indicates that the results of the SELECT statement that precedes UNION will be combined with the results of the SELECT statement that follows UNION.
When you use the ALL keyword, duplicate rows are not removed from the combined set that is produced by the union. This can dramatically improve the performance of the query, because Access does not have to check the results for duplicate rows. You should use the ALL keyword if any of the following conditions is true:
You are certain that the select queries will not produce any
duplicate rows.
It does not matter if your results have duplicate rows.
You want to see duplicate rows.
EDITED
After your edition and what I've got it from your question then this might be helpful. You need to loop that queries to get an array of results as
$tablename = array('name1','name2','name3','name4','name5','name6','name7');
$results = array();
foreach($tablename as $key => $value){
$results[$key] = $this->db->query("select * from ".$value."")->result_array();
}
Multiple select query in codigniter
$this->db->select('t1.*, t2.*');
$this->db->from('table1 AS t1, table2 AS t2');
$query = $this->db->get();
$row = $query->result_array();
print_r($row);
I am trying to show something similar to related products on on my website. I have tested the following query, and I get no errors; but I get no results either.
<?php
$relatedStmt = $db->query("SELECT * FROM items WHERE tag LIKE id = 1 LIMIT 3");
?>
I also tried %1% and it displayed ALL the results, I assumed the code was thinking the query was just SELECT * FROM items.
The tags in the column are displayed in the following format: tagone two three four, so I am trying to display the products that have similar tags, hence why I used the LIKE clause.
Table screenshot
The current query is to relate with this query: SELECT * FROM items WHERE id = 1. So LIKE id = 1 is to find the tags that match this query to show the related products.
LIKE doesn't work the way you seem to expect. It's a character for character comparison, with wildcards, between the operands.
Of the mysql functions, closest to what you want is probably LOCATE or FIND_IN_SET. There are split solutions in other questions, e.g. "Can Mysql Split a column?" and "Split a MYSQL string from GROUP_CONCAT into an ( array, like, expression, list) that IN () can understand". However, even so there is no good way to compare the individual tags in your concatenated tag column with the individual tags of the other rows in your table.
Therefore, I think you'd be better off moving the tags into their own table with item_id as a foreign key. Then the solution is trivial (SQLFiddle):
-- Related Items
SELECT *
FROM items
WHERE id in (SELECT DISTINCT item_id
FROM tags t
JOIN (SELECT tag
FROM tags
WHERE item_id = 1
) t1 ON t1.tag = t.tag
WHERE item_id != 1
)
;
i am unsure about that id = 1 thing in your query but anyway you could try this: SELECT * FROM items WHERE tag LIKE '%search_this_tag%' LIMIT 3
It's been a while since I needed help, but today I'm here to basically get assistance from your knowledge. I'm currently quite stuck on a very annoying SQL problem, which is the following.
I have two tables. Painteditems, and specialitems. Both tables have unique column names (painteditemid, specialitemid etc), yet both tables share similar values. I want to get results from both tables.
Let's say this is my setup:
PaintedItems
paintedItemName
paintedItemColor
visible
SpecialItems
specialItemName
specialItemColor
visible
I used this query:
SELECT *
FROM `painteditems` AS pa,
`specialitems` AS sp
WHERE (pa.`visible` = 1
OR sp.`visible` = 1)
AND (pa.`painteditemname` = 'itemname1'
OR sp.`specialitemname` = 'itemname1')
AND (pa.`painteditemcolor` = 'black'
OR sp.`specialitemcolor` = 'black')
That resulted in:
Showing rows 0 - 29 ( 259,040 total, Query took 39.4352 sec)
even though both tables contain only 10.000 rows altogether. Adding this did nothing:
GROUP BY pa.`painteditemid`, sp.`specialitemid`
Still 260k rows. How should I approach this?
Thank you in advance.
edit: fixed spacing, code blocks
Sure sounds like you want a UNION between the two tables. Right now, you are getting a cartesian product which is why the results are so large:
select *, 'painted' Source
from painteditems
where visible = 1
and painteditemname = 'itemname1'
and painteditemcolor = 'black'
union all
select *, 'special' Source
from specialitems
where visible = 1
and specialitemname = 'itemname1'
and specialitemcolor = 'black'
You will need to replace the SELECT * with your column names. Also the number of columns and datatypes must match in both queries.
UNION ALL will return all rows from both tables, if you only want DISTINCT rows then you will want to use UNION
The UNION operator is used to combine the result-set of two or more SELECT statements. Defiantly You can make use of UNION as shown in the #bluefeet's answer If you meet below conditions.
SELECT statement within the UNION must have the same number of
columns
The columns must also have similar data type
The columns in each SELECT statement must be in the same order.
I would do this with a union all in the subquery:
select *
from ((select paintedItemName as ItemName, paintedItemColor as ItemColor, visible, 'Painted' as which
from painteditems
) union all
(select specialItemName, SpecialItemColor, visible, 'Special' as which
from specialitems
)
) t
where visible = 1 and itemname = 'itemname1' and itemcolor = 'black'
This allows you to have only one set of results. In a union, the column names come from the first subquery, which this renames to more generic names. The reason I prefer this approach is because the where clause does not need to be repeated multiple times -- which can lead to errors and maintenance problems.
I have page that display information from two different tables , and for that I have two queries.
There is no related info between these two tables.
Since both queries may contain a lot of information, I need create pagination.
BUT I don't want two separate paginations, I want only one that will contain results from query 1 and query 2 together.
How can I do that?
The only idea I have is to fetch all info of both queries into arrays, then combine the arrays into one, then create pagination that based on that array.
That of course would not help save resources.
You could use a union - the columns you're displaying must line up, so something like this should work:
select
col1 col1_alias,
col2 col2_alias,
...
from
table1
where
...
union
select
col1,
col2,
...
from
table2
where
...
order by col1_alias, col2_alias
limit 10
Basically the union will pull all the data together, and the order by and limit will apply to the whole result set.
The names of the columns don't need to match in the second select, but use column names from the first select for your order by (or create aliases, which is probably more readable depending on your dataset).
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