How I create this mysql select query? - mysql

I do have a mysql product table with the columns of id, name, description, and category_id.
This is the result when it select id, name and category_id.
+----+-------------+----------------------------+
| id | category_id | name |
+----+-------------+----------------------------+
| 6 | 1 | category name |
| 7 | 2 | category name |
| 8 | 3 | category name |
| 9 | 2 | category name |
| 11 | 2 | category name |
| 15 | 3 | category name |
| 13 | 4 | category name |
| 14 | 1 | category name |
| 15 | 2 | category name |
| 16 | 2 | category name |
| 17 | 3 | category name |
| 18 | 4 | category name |
| 19 | 1 | category name |
+----+-------------+----------------------------+
My question is, Just I need to select newly added 4 products from above table. These 4 products should be 4 different categories.
This is how I tried it. But its not working for me.
SELECT p.id
, p.category_id
, p.name
, p.description
FROM products p
WHERE p.category_id IN ('1', '2', '3', '4')
ORDER BY added_date DESC
LIMIT 4
+----+-------------+--------+-------------+
| id | category_id | name | description |
+----+-------------+--------+-------------+
| 8 | 4 | dfadff | dfasf |
| 7 | 4 | dffdsf | fdfdfaf |
| 6 | 3 | fdfdsf | fdsfdsfd |
| 5 | 2 | dffdsf | dfsfsf |
+----+-------------+--------+-------------+
4 rows in set (0.00 sec)
Result from above query:

You have to first decide which product is the "last" for each category, that can be simple max(id) if your id is autoincrementing. Then you pick products by these ids:
select p.id, p.category_id, p.name
from products p
join (
select max(id) id from products group by category_id
) tmp using(id);
It can be seen in action at http://sqlfiddle.com/#!9/c86fa/2
If you need to check the WHERE p.category_id IN ('1', '2', '3', '4') part, it is enough to put it inside the subquery.

Related

MySQL Select only some rows in pivot table and all rows in table

I have a table articles with an id and a name, a table company with an id and a name and a pivot table (article_company) with an id, article_id, company_id, and a price.
I want to associate an article with a company so I need a request with all product and if they're associate to this company.
I tried this query:
SELECT
article_id,
name,
price AS price,
1 AS associated
FROM articles
JOIN article_company ON articles.id = article_company.article_id
WHERE company_id = 26
UNION
SELECT
id AS article_id,
name,
NULL AS price,
0 AS associated
FROM articles
GROUP BY article_id
but unfortunately I have both articles from articles table and company_article.
If it is not really clear, I want to have all articles rows but if an article is in company_article I want the row from that table.
EDIT : data tables :
- articles :
+----+--------------+
| id | name |
+----+--------------+
| 1 | Aez |
| 2 | aze |
| 3 | za |
| 4 | azee |
| 5 | article test |
| 6 | test 2 |
| 7 | Test 3 |
+----+--------------+
-company_article :
+------------+------------+-------+
| article_id | company_id | price |
+------------+------------+-------+
| 5 | 26 | 54.00 |
| 3 | 26 | 8.90 |
+------------+------------+-------+
What I have and rows I want :
+------------+--------------+-------+------------+
| article_id | name | price | associated |
+------------+--------------+-------+------------+
| 5 | article test | 54.00 | 1 | <
| 3 | za | 8.90 | 1 | <
| 1 | Aez | NULL | 0 | <
| 2 | aze | NULL | 0 | <
| 3 | za | NULL | 0 |
| 4 | azee | NULL | 0 | <
| 5 | article test | NULL | 0 |
| 6 | test 2 | NULL | 0 | <
| 7 | Test 3 | NULL | 0 | <
+------------+--------------+-------+------------+
Try something like this:
SELECT * FROM articles a LEFT OUTER JOIN company_article ca ON a.id =
ca.article_id;
This is the explanation for left outer join:
http://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqlj18922.html
Okay so I find myself this is the request I made :
SELECT article_id as id, name, price
res.associated as associated, created_at
FROM (
SELECT
article_id, name, price
1 AS associated, created_at
FROM articles
JOIN article_company ON articles.id = article_company.article_id
WHERE company_id = $id
UNION ALL
SELECT
id AS article_id, name, null as price
0 AS associated, created_at
FROM articles) AS res
GROUP BY article_id
ORDER BY associated DESC

MYSQL Join returns duplicate column name

I am new to SQL and have the following challenge, I have a table on the left that has products assigned to a single company and denoted by a ref_id (it comes from another table, and I have simplified it for sake of question) and I have a master list. I want to compare all the products for company "A" against the master list and show all the products company A has not subscribed to. I am using JOIN and end up getting duplicate column names which throws my PHP program off. Here is what I have tried several syntax for UNION, RIGHT JOIN, LEFT JOIN and NOT operators, and the below is the closest I have gotten, however I am getting duplicate column names and I only need the last table with the last 2 columns. Please advise.
mysql> select ref_id, product_id, short_name from ap_company_product order by ref_id, product_id;
+--------+------------+------------+
| ref_id | product_id | short_name |
+--------+------------+------------+
|      2 | 10         | product 10 |
|      2 | 11         | product 11 |
|      2 | 12         | product 12 |
|      2 | 15         | product 15 |
|      2 | 17         | product 17 |
|      2 | 21         | product 21 |
|      3 | 11         | product 11 |
|      3 | 13         | product 13 |
|      3 | 17         | product 17 |
|      3 | 20         | product 20 |
+--------+------------+------------+
10 rows in set (0.00 sec)
THE MAIN LIST
mysql> select  product_id, short_name from ap_company_product_list;
+------------+-------------+
| product_id | short_name  |
+------------+-------------+
| 10         | product 10  |
| 11         | product 11  |
| 12         | product 12  |
| 13         | product 13  |
| 14         | product 14  |
| 15         | product 15  |
| 16         | product 16  |
| 17         | product 17  |
| 18         | product 18  |
| 19         | product 19  |
| 20         | product 20  |
| 21         | product 21  |
| 22         | product 22  |
+------------+-------------+
13 rows in set (0.00 sec)
Another SQL which is the actual results I need
SELECT aa.product_id as product_id, aa.short_name as short_name, aa.ref_id as ref_id, bb.product_id as product_id, bb.short_name as short_name FROM (select ref_id, product_id, short_name from ap_company_product where ref_id=2) aa RIGHT OUTER JOIN ap_company_product_list bb ON aa.product_id = bb.product_id where aa.product_id is NULL;
+------------+------------+--------+------------+------------+
| product_id | short_name | ref_id | product_id | short_name |
+------------+------------+--------+------------+------------+
| NULL       | NULL       |   NULL | 13         | product 13 |
| NULL       | NULL       |   NULL | 14         | product 14 |
| NULL       | NULL       |   NULL | 16         | product 16 |
| NULL       | NULL       |   NULL | 18         | product 18 |
| NULL       | NULL       |   NULL | 19         | product 19 |
| NULL       | NULL       |   NULL | 20         | product 20 |
| NULL       | NULL       |   NULL | 22         | product 22 |
+------------+------------+--------+------------+------------+
7 rows in set (0.01 sec)
Just use this:
SELECT bb.product_id as product_id, bb.short_name as short_name FROM (select ref_id, product_id, short_name from ap_company_product where ref_id=2) aa RIGHT OUTER JOIN ap_company_product_list bb ON aa.product_id = bb.product_id where aa.product_id is NULL;
BTW, I would prefer this one:
SELECT product_id, short_name FROM ap_company_product_list WHERE product_id NOT IN (SELECT product_id FROM ap_company_product);

Getting specific values from many-to-many relationships

My database looks like this, I have client accounts which are assigned to specific profiles, and I have profiles which are assigned to specific categories, like in this schema:
| categories | | profiles | | categories_map |
--------------- ------------- ----------------------------
| ID | name | | ID | name | | ID | profile_id | cat_id |
--------------- ------------- ----------------------------
| 1 | cat1 | | 1 | p1 | | 1 | 1 | 1 |
| 2 | cat2 | | 2 | p2 | | 2 | 2 | 1 |
| 3 | cat3 | | 3 | p3 | | 3 | 3 | 1 |
| 4 | p4 | | 4 | 1 | 2 |
| 5 | 3 | 2 |
| 6 | 4 | 3 |
| profiles_map |
-----------------------------
| ID | profile_id | acc_id |
-----------------------------
| 1 | 1 | 1 |
| 2 | 3 | 1 |
| 3 | 4 | 1 |
I need to get categories assigned to accounts - which means when I want to get categories for acc_id = 1, I should get categories with ID 2 and 3 ( category with ID 2 doesn't fit because it contains profile with ID 2 which isn't assigned to this account). I tried this query but it doesn't work
select cats.id from profiles_map map
right join categories_map catm on catm.profile_id = map.profile_id
right join categories cats on cats.id = catm.cat_id
where catm.profile_id in (select profile_id from profiles_map where acc_id = 1)
and map.acc_id = 1 group by cats.id;
Could anybody help me with this question?
Can you try this one?
SELECT DISTINCT C.ID
FROM profiles_map PM
INNER JOIN categories_map CM ON CM.profile_id = PM.profile_id
INNER JOIN categories C ON C.ID = CM.cat_id
WHERE PM.acc_id= 1
If you want to get only category id, Please try following query:
SELECT DISTINCT cm.cat_id FROM categories_map cm
WHERE cm.profile_id in
(SELECT profile_id FROM profiles_map WHERE acc_id = 1)
Or if want to get category name and id then , use following query:
SELECT cat.id,cat.name FROM categories cm
WHERE cat.id in (SELECT DISTINCT cm.cat_id FROM categories_map cm
WHERE cm.profile_id in
(SELECT pm.profile_id FROM profiles_map pm WHERE pm.acc_id = 1))

SUM rows only if it does not have one of the multivalued values

Movies table:
+----+------+---------+
| id | title | price |
+----+------+---------+
| 1 | movie1 | 20 |
| 2 | movie2 | 15 |
| 3 | movie3 | 25 |
| 4 | movie4 | 10 |
+----+------+---------+
Categories table:
+-----+--------+
| idd | cat |
+-----+--------+
| 1 | horror |
| 1 | comedy |
| 2 | drama |
| 2 | sci-fi |
| 3 | action |
| 4 | sci-fi |
+-----+--------+
I want to make a query to sum the prices of all the movies except the ones that have 'sci-fi' as one of its categories.
I have tried this:
select count(distinct id) as no_of_movies, sum(price) as price
from (select distinct id,price
from movies,categories
where id=idd and not cat='sci-fi') as tt;
But it only works with the movies that have only one category, like 'movie4'.
It still sums 'movie2' as 'drama'.
So how can I also skip 'movie2' so that the output will be 45 instead of 60?
try this:
select count(distinct id) as no_of_movies, sum(price) as price
from (select distinct id,price
from movies,categories
where id=idd and id not in (select idd
from categories
where cat = 'sci-fi')) as tt;

multilevel mysql query with a weird setup

I have a problem. I am a codding newbie and learning php and mysql as i go.
i am working on an application and ran into a problem that i cant figure out.
I have three tables:
category:
+-----------+----------+--------------------+
| id | name | sort | active |
+-----------+----------+--------------------+
| 1 | apple | 1 | 1 |
| 2 | mango | 2 | 1 |
| 3 | blueberry| 3 | 0 |
+-----------+----------+--------------------+
service :
+-----------+----------+----------------------------------------+
| id | category_id | name | sort |active| process_time |
+-----------+------+------+--------+------+------+--------------+
| 1 | 1 | slices | 1 | 1 | 2 hours |
| 2 | 1 | half | 2 | 1 | 6 hours |
| 3 | 2 | slices | 1 | 1 | 1 hour |
| 4 | 2 | whole | 2 | 1 | 6 hours |
| 5 | 3 | bunch | 1 | 0 | 12 hours |
| 6 | 3 | a lot | 2 | 1 | 10 hours |
+-----------+------+---------+------+-------------+-------------+
user_price:
+-----------+----------+------+-------+---------+---------+---------+---------+
| id | user_id | 1 | 2 | 3 | 4 | 5 | 6 |
+-----------+----------+------+-------+---------+---------+---------+---------+
| 1 | 20 | 1 | 1 | 5 | 4 | 6 | 6 |
| 2 | 22 | 2 | 1 | 2 | 3 | 5 | 1 |
| 3 | 32 | 3 | 2 | 7 | 4 | 1 | 3 |
+-----------+----------+------+-------+---------+---------+---------+---------+
Categories have the categories that i sell in my store.
Services have the services that i offer in my store they correspond to the categories and are unique to only that category.
Prices have the user prices that i charge my customers every user has a different price the column names in the price table correspond to the services id.
Here is a SQLFiddle with sample data
Now here is the problem, in one sweep i would like to get a row that contains columns from all three tables for user_id 22 (user_id is only used for prices)
+---------------+----------------+-----------------+------------------+-----------+
| service_id | category_name | service_name | process_time | price |
+---------------+----------------+-----------------+------------------+-----------+
| 3 | mango | slices | 1 hour | 2 |
+---------------+----------------+-----------------+------------------+-----------+
Any ideas???
Try
SELECT s.id service_id,
c.name category_name,
s.name service_name,
s.process_time,
p.`3` price
FROM service s JOIN category c
ON s.category_id = c.id JOIN user_price p
ON p.user_id = 22
WHERE s.id = 3
Output:
| SERVICE_ID | CATEGORY_NAME | SERVICE_NAME | PROCESS_TIME | PRICE |
--------------------------------------------------------------------
| 3 | mango | slices | 1 hour | 2 |
Here is SQLFiddle demo
Now while it's not too late please normalize your user_price table. That will save you a lot of headache in the long run.
Your renewed schema for this table might look like
CREATE TABLE IF NOT EXISTS user_price
(
id int(11) NOT NULL AUTO_INCREMENT,
user_id int(11) NOT NULL,
service_id int(11) NOT NULL,
price decimal(19,2) DEFAULT '0.00',
PRIMARY KEY (id),
FOREIGN KEY (service_id) REFERENCES service (id),
UNIQUE KEY (user_id, service_id)
);
And the proper query using this table
SELECT s.id service_id,
c.name category_name,
s.name service_name,
s.process_time,
p.price
FROM service s JOIN category c
ON s.category_id = c.id JOIN user_price p
ON s.id = p.service_id
AND p.user_id = 22
WHERE s.id = 3
Here is a SQLFiddle demo. In this example the table has been named user_price1 to show you both queries side-by-side.