Sql query showing additional results - php

i have
SELECT s.*
FROM shop
WHERE s.family IN (SELECT s2.family FROM shop s2 WHERE (s2.money like "%k%"))
it does return "ticket" which contanis the k letter but in addition it returns all the other results that doesn't have "k" in it
here is the table of shop :
+----+--------+-------+
| id | family | money |
+----+--------+-------+
| 1 | 1 | card |
| 2 | 1 |Cheque |
| 3 | 2 |coins |
| 4 | 2 |ticket |
+----+--------+-------+
i am using
IN (SELECT s2.family FROM shop s2 WHERE (s2.money like "%k%"));
because i want to show the results as a group of rows with the same family, i got this query from an other question

Did you try:
SELECT *
FROM shop
WHERE money LIKE "%text%";
You are using a statement from a previous question you posted that might not be valid in this situation.

Related

Finding inner join mysql with array [duplicate]

This question already has answers here:
How to join two tables using a comma-separated-list in the join field
(5 answers)
Closed 2 years ago.
I have two tables, First one is products where it has list of products with some specifications, in the other hand I have a table with clients and what type of product they want, they might want a product in any town of a list exactly as explained in the following tables,
Products Table like
| id | owner | userid | city | town | status | price |
| 1 | jon spee | 10 | 10 | 4 | 0 | 10500 |
| 2 | Hiss Roe | 10 | 7 | 9 | 0 | 20000 |
| 3 | John Smi | 10 | 10 | 12 | 0 | 10000 |
Clients Table like
| id | fullname | userid | city | towns | status | price |
| 1 | name 1 | 10 | 10 |4,8,6,2| 0 | 20000 |
| 2 | name 2 | 10 | 7 | 7,2,9 | 0 | 25000 |
| 3 | name 3 | 10 | 10 | 1 | 0 | 20000 |
MySQL Query :
SELECT *
FROM clients
INNER JOIN products
ON (
clients.userid = products.userid AND
clients.price >= products.price AND
clients.city = products.city AND
clients.status = products.status
I want it to check also in towns like for each town it executs this query (dynamically),
(products.town LIKE '%4%' OR products.town LIKE '%8%' OR products.town LIKE '%6%' OR products.town LIKE '%2%')
You could go with this query
SELECT *
FROM clients
INNER JOIN products
ON (
clients.userid = products.userid AND
clients.price >= products.price AND
clients.city = products.city AND
find_in_set(clients.town, products.town) AND
clients.status = products.status
you can also fetch it in php and create your statement based on the results fetched
Your primary effort should go into fixing your data model. Don't store multiple integer values in a string column. You should have a separate table to store the relation betwen clients and towns, which each tuple on a separate row.
That said: for your current design, you can join on find_in_set():
on
clients.userid = products.userid
and ...
and find_in_set(product.town, client.towns)

How to select only one record of each category?

Products :
--------------------------------------------
| ID | Group | Name | Sold |
--------------------------------------------
| 1 | A | Dell | 0 |
--------------------------------------------
| 2 | A | Dell | 0 |
--------------------------------------------
| 3 | B | Dell | 1 |
--------------------------------------------
| 4 | B | Dell | 1 |
--------------------------------------------
| 5 | C | Dell | 0 |
--------------------------------------------
| 6 | C | Dell | 1 |
--------------------------------------------
Hi everyone, i have a table (products) stored in MySql with many records, for now i'm using this query SELECT * FROM products WHERE sold = 0, in results i get :
--------------------------------------------
| ID | Group | Name | Sold |
--------------------------------------------
| 1 | A | Dell | 0 |
--------------------------------------------
| 2 | A | Dell | 0 |
--------------------------------------------
| 5 | C | Dell | 0 |
--------------------------------------------
i want to get only one record from each group, so the results will be like :
--------------------------------------------
| ID | Group | Name | Sold |
--------------------------------------------
| 1 | A | Dell | 0 |
--------------------------------------------
| 5 | C | Dell | 0 |
--------------------------------------------
You could easily do this by using a distinct clause and removing the id column. If you want to keep the id column you need to specify how one would chose which id to keep.
select distinct
`group`
, name
, sold
from
products
where
sold = 0;
To keep the row with the smallest id (as your example shows) something along the lines of the example below would work.
select
id
, `group`
, name
, sold
from
products
where
sold = 0
and id = (
select
min(p.id)
from
products p
where
p.`group` = products.`group`
and p.sold = 0
);
First, change your field named Group to something like Group_Name. GROUP is a reserved keyword, and if it is not causing you problems now it probably will later.
Second, you should ask yourself what you are really after. The following query should generate your desired result. It adds an additional condition where the IDs that are returned are the lowest numbered ID in each group.
SELECT * FROM products
WHERE sold = 0
AND ID IN (SELECT MIN(ID) FROM products WHERE sold = 0 GROUP BY Group_Name)
Why do you want that, though? That is not a normal desired end state. You should ask yourself why you care about the ID. It looks like your goal is to figure out which products have not sold anything. In that case, I would recommend this instead:
SELECT DISTINCT Group_Name, Name
FROM products
WHERE sold = 0
ORDER BY Group_Name, Name
I found the solution by using the statement GROUP BY,
SELECT * FROM products WHERE sold = 0 GROUP BY group
in the results now, i get only one record for each group and the minimal id without adding any other statement, and in my real table i am using product_group instead of group because it's a reserved word.
Try this:
SELECT `ID`, `Group`, `Name`, `Sold` FROM products WHERE sold = 0 GROUP BY `Group`;

mysql select distinct while ignoring one column

I have the following problem: I have a table import_data
The table is enriched something like this
| id | profile_id | sku | vendor | price | importRun |
| 1 | 39 | 123 | myVen | 2.0 | 1 |
| 2 | 39 | 456 | myVen | 2.0 | 1 |
| 3 | 39 | 123 | myVen | 3.0 | 2 |
What I need to get is an output of all elements, but only once. Every sku must be unique. To make it even worse, I need the newest data, if they are redundant.
My output should be like this:
| id | profile_id | sku | vendor | price | importRun |
| 2 | 39 | 456 | myVen | 2.0 | 1 |
| 3 | 39 | 123 | myVen | 3.0 | 2 |
Short Summary about the structure:
ID = PK
sku = a unique identifier for an article
importRun = Needed for comparision.
So, to explain it: I have an import-script, which reads a given CSV-file and imports all articles listed in it. I get this CSV-file in a regular period (once a week). I need to collect all data and save it, to create a price-evolution later on.
After every Import, I increment the number of importRun, so that no information is lost (remember, I can't use REPLACE INTO or INSERT IGNORE.
Now, when I export it, I need the newest Data, if a SKU occures multiple times. In this case, the SKU 123 is inserted 2 times on 2 different runs. That means, since my newest Run had the number 2, I need this tupel (and ignore the first one).
When I work with DISINCT, it would still output the same table, since they aren't distinct at all, because importRun differs.
I should be able to use GROUP BY, but I couldn't figure out which value will be taken, the first- or the last one? (importRun 1 or 2)
Update 1
Followed by the idea of #mitkosoft, I tried the following:
SELECT DISTINCT t1.*
FROM import_data t1
INNER JOIN import_profiles imp on t1.profile_id = imp.id
INNER JOIN (
SELECT DISTINCT sku, MAX(importRun) AS importRun
FROM import_data
GROUP BY sku ) t2
ON t1.sku = t2.sku
WHERE imp.creditornr = 73329
AND t1.vendor = 'rackmountit'
AND t1.importRun = t2.importRun
** Update 2 **
I added the complete Structures for all tables, which are relevant.
Import-Data:
|
Import-Profiles
But i still get duplicates :/
All you need to do is to determine MAX(importRun) for each sku:
SELECT
t1.*
FROM
import_data t1
INNER JOIN (
SELECT sku, MAX(importRun) AS importRun FROM import_data GROUP BY sku
) t2
ON t1.sku = t2.sku
AND t1.importRun = t2.importRun
Output is:
+----+------------+-----+--------+-------+-----------+
| id | profile_id | sku | vendor | price | importRun |
+----+------------+-----+--------+-------+-----------+
| 2 | 39 | 456 | myVen | 2.0 | 1 |
| 3 | 39 | 123 | myVen | 3.0 | 2 |
+----+------------+-----+--------+-------+-----------+
2 rows in set
Perhaps you could join on the same table where sku = sku

mysql most popular articles in most popular categories [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have 'articles table':
id,
category_id
categories table:
id
view counts table:
id,
article_id,
ip,
What i need is mysql query which will give 5 categories having biggest views count of articles total (most often read category). Additionaly in each category must be a list of articles having biggest view count (most often read 5 articles in category)
So query should return something like:
sport, article1
sport, article2
sport, article3
sport, article4
sport, article5
tv, article6
tv, article7
tv, article8
tv, article9
tv, article10
etc...
Additionaly it would be great to have how many times article and category was watched but this is not necessary.
I have tried count all with having but with no success.
Regards.
To do this in MySQL you have to mimic the row_number() over (partition by category) functionality that would otherwise be available in other databases.
I've tested out the query below using some sample data here:
Fidde:
http://sqlfiddle.com/#!9/2b8d9/1/0
Query:
select id, category_id
from(
select x.*,
#row_number:=case when #category_id=x.category_id then #row_number+1 else 1 end as row_number,
#category_id:=x.category_id as grp
from (select art.id, art.category_id, count(*) as num_art_views
from articles art
join (select art.category_id, count(*)
from view_counts cnt
join articles art
on cnt.article_id = art.id
group by art.category_id
order by 2 desc limit 5) topcats
on art.category_id = topcats.category_id
join view_counts cnt
on art.id = cnt.article_id
group by art.id, art.category_id
order by art.category_id, num_art_views desc) x
cross join (select #row_number := 0, #category_id := '') as r
) x where row_number <= 5
For some clarification, this will show the top 5 articles within the top 5 categories.
Using LIMIT was sufficient to get the top 5 categories, but to get the top 5 articles WITHIN each category, you have to mimic the PARTITION BY of other databases by using a variable that restarts at each change in category.
It might help to understand if you run the just the inner portion, see fiddle here:
http://sqlfiddle.com/#!9/2b8d9/2/0
The output at that point is:
| ID | CATEGORY_ID | NUM_ART_VIEWS | ROW_NUMBER | GRP |
|-----------|-------------|---------------|------------|--------|
| article16 | autos | 2 | 1 | autos |
| article14 | planes | 2 | 1 | planes |
| article12 | sport | 4 | 1 | sport |
| article3 | sport | 3 | 2 | sport |
| article4 | sport | 3 | 3 | sport |
| article1 | sport | 3 | 4 | sport |
| article2 | sport | 3 | 5 | sport |
| article5 | sport | 2 | 6 | sport |
| article15 | trains | 2 | 1 | trains |
| article13 | tv | 6 | 1 | tv |
| article9 | tv | 3 | 2 | tv |
| article6 | tv | 3 | 3 | tv |
| article7 | tv | 3 | 4 | tv |
| article8 | tv | 3 | 5 | tv |
| article10 | tv | 2 | 6 | tv |
You can easily exclude anything not <= 5 at that point (which is what the above query does).

How do I compare 2 tables looking for missing items

I have two tables one that contains a huge list of items and another that trading for those items.
Here are examples tables:
The main table
| ID | TITLE | STATUS | TRADE |
-------------------------------
| 1 | test1 | 1 | 1 |
| 2 | test2 | 1 | 1 |
| 3 | test3 | 1 | 0 |
| 4 | test4 | 0 | 1 |
The trade table
| ID | TRADER | ITEM | URL |
------------------------------------------------------
| 1 | 2 | 1 | HTTP://www.test.com/itemOne |
| 2 | 5 | 3 | HTTP://www.test.com/itemThree |
| 3 | 5 | 4 | HTTP://www.test.com/itemFour |
Say I want to have a list of all the items that are not being traded by trader 5 and have a status of 1. So when trader 5 comes to the site they will be able to select the remaining items to trade.
Here is what I have tried:
$sql = "SELECT m.id, m.title
FROM main AS m, trade AS t
WHERE m.trade >= 1 && m.status = 1 &&
t.trader <>". mysql_real_escape_string($traderID);
This code just doesn't work. Any ideas on this?
It is not clear to me what column in Trades is an FK to Main. Below, I have assumed it is the Item column:
select m.id, m.title
from Main m
where not exists (
select *
from trade
where m.id = item
and trader = 5
)
and m.status = 1
Try this:
SELECT id, title FROM main
WHERE status = 1 AND id NOT IN
(SELECT item FROM trade WHERE trader = 5);
This will grab a list of every title in main with a status of 1, but limit the items based on a subquery which gets a list of ids already traded by trader 5 (i.e. items "not in" the list of items returned as having been traded by trader 5).
I'll leave it to you to update the query to be parameterized as needed.
Note that I'm assuming that item in trade is a foreign key to the id field in main, since you didn't specify it.

Categories