With php I am trying to get data from 2 different tables :
Table : products
+-------+---------+----------+
| pcode | product | category |
+-------+---------+----------+
| 1 | jeans | men |
+-------+---------+----------+
| 2 | shirt | men |
+-------+---------+----------+
Table : colors
+-------+---------+
| pcode | colors |
+-------+---------+
| 1 | blue |
+-------+---------+
| 1 | black |
+-------+---------+
| 1 | white |
+-------+---------+
| 2 | yellow |
+-------+---------+
Result I want should be like :
+-------+---------+----------+---------------------+
| pcode | product | category | colors |
+-------+---------+----------+---------------------+
| 1 | jeans | men | black, blue, white |
+-------+---------+----------+---------------------+
| 2 | shirt | men | yellow |
+-------+---------+----------+---------------------+
Please guide me.
Thanks in advance.
Vikram
SELECT p.pcode,product,category,GROUP_CONCAT(colors) as colors
FROM products p JOIN colors c
ON p.pcode=c.pcode
GROUP BY product
Mihai's Query also working..
Can also try this..
select p.*, group_concat(colors separator ',') colors from products p left outer join colors c on p.pcode=c.pcode group by p.pcode;
NOTE:You could try to use PDO or MySqli libary(links bellow) to run this SQL Statement
You could try this SQL statement i think it will do the job but will show the rows in a different way that you requested just give it a try:
SELECT colors.pcode , products.products ,products.category , colors.colors
FROM colors
INNER JOIN FIRST ON colors.pcode = products.pcode
Results:
Or if you wanted like you asked you should seperate the work in multiple SQL Satatement:
SELECT colors FROM colors WHERE pcode = 1
And with some SQL Sattement get all the colors
Then get the products and the productsand categorys this way:
SELECT product , category FROM products WHERE pcode = 1
And also with some like this you will get all what you need
But i would prefer the first one as it is more handy and faster.
Links:
PDO:
http://php.net/manual/en/book.pdo.php
MYSQLI:
http://www.php.net/mysqli
Have a nice day :)
Related
I have two tables that look like this:
Table cars
+--------+-----------+-------+---------+
| car_id | attribute | value | brand |
+--------+-----------+-------+---------+
| 1 | colore | rosso | Ferrari |
| 1 | prezzo | 100 | Ferrari |
| 2 | couleur | bleu | Renault |
| 2 | prix | 50 | Renault |
| 3 | colore | blu | Ferrari |
| 3 | prezzo | 100 | Ferrari |
+--------+-----------+-------+---------+
Table translations
+--------------------+----------------+---------+----------------------+------------------+
| original_attribute | original_value | brand | translated_attribute | translated_value |
+--------------------+----------------+---------+----------------------+------------------+
| colore | rosso | Ferrari | color | red |
| prezzo | 100 | Ferrari | price | 100 |
| colore | blu | Ferrari | color | blue |
| couleur | bleu | Renault | color | blue |
| prix | 50 | Renault | price | 50 |
+--------------------+----------------+---------+----------------------+------------------+
I am trying to get to a table that looks like this:
+-------------------+-------+-------------+--------------------+
| translated_car_id | color | price | translated_brand |
+-------------------+-------+-------------+--------------------+
| 1 | red | 100 | Ferrari |
| 2 | blue | 50 | Renault |
| 3 | blue | 100 | Ferrari |
+-------------------+-------+-------------+--------------------+
At the moment, I am using below code. It works, but is excruciatingly slow.
SELECT
car_id translated_car_id,
MAX(CASE
WHEN translations.translated_attribute = 'color' THEN translations.translated_value
END) color,
MAX(CASE
WHEN translations.translated_attribute = 'price' THEN translations.translated_value
END) price,
brand translated_brand
FROM
cars c
INNER JOIN
translations ON (c.attribute = translations.original_attribute
AND c.brand = translations.brand
AND c.value = relations.original_value)
GROUP BY c.car_id
Anybody have an idea on how to make the query or the structure more efficient? Would really appreciate it.
Thanks in advance
From what I can find MySql doesn't have hash matches, which would be useful here. So I'm assuming that everything is being done as nested loop joins.
My concern is that because there isn't an index on translations, for every row in cars it has to scan the translations table to find the matching rows.
I would recommend a clustered index on translations(original_value, brand, original_attribute). (ms-sql does best with most specific first everything else being equal, not sure about MySql) That way it can go right to the row that it needs to match to. That should allow queries with one car to be done quickly.
If you can reduce the translations from manufacturer to language that would certainly help with the size of the translation table, but you would have to be sure that it works with your dataset because it does take away a level of flexibility.
I think that MySql will be able to use the index on cars to process the GROUP BY efficiently, but I will propose a more normalized schema where you don't need the group by.
car
-------------
car_id
brand
car_attribute
------------
car_id
attribute
value
clustered_index(car_id, attribute)
brand_attribute
------------
brand_attribute_id
brand
attribute
translated_attribute
clustered_index(brand, translated_attribute)
brand_attribute_value
------------
brand_attribute_id
value
translated_value
clustered_index(brand_attribute_id, value)
And here's the query to do it that way.
SELECT
car.car_id,
color_brand_value.translated_value AS color,
price_brand_value.translated_value AS price,
car.brand
FROM
car
INNER JOIN brand_attribute AS color_brand
ON color_brand.brand = car.brand
AND color_brand.translated_attribute = 'color'
INNER JOIN car_attribute AS color_attribute
ON color_attribute.car_id = car.car_id
AND color_attribute.attribute = brand.attribute
INNER JOIN brand_attribute_value AS color_brand_value
ON color_brand_value.brand_attribute_id = color_brand.brand_attribute_id
AND color_brand_value.value = color_attribute.value
INNER JOIN brand_attribute AS price_brand
ON price_brand.brand = car.brand
AND price_brand.translated_attribute = 'price'
INNER JOIN car_attribute AS price_attribute
ON price_attribute.car_id = car.car_id
AND price_attribute.attribute = brand.attribute
INNER JOIN brand_attribute_value AS price_brand_value
ON price_brand_value.brand_attribute_id = price_brand.brand_attribute_id
AND price_brand_value.value = price_attribute.value
It's definitely more complicated to do it this way. With your situation I'm not sure it's better, but something to consider if the first option isn't good enough.
My background is in mssql, so there may be differences that I'm not aware of. Please leave comments if I've missed or got something wrong.
My table:
+----+------------+-------+-------+
| id | Name | Type | Code |
+----+------------+-------+-------+
| 1 | /Color | black | cod-1 |
| 2 | Colorless | black | cod-2 |
| 3 | Colorful | black | cod-1 |
| 4 | Color/ | black | cod-3 |
| 5 | Colored | blue | cod-1 |
| 6 | Bottle | black | cod-1 |
| 7 | Bottles | black | cod-2 |
| 8 | Bottle/z | black | cod-1 |
| 9 | Bottleneck | blue | cod-1 |
+----+------------+-------+-------+
For a selected Type, I need to group by (like) Names and count by distinct code.
In the end, the final count must give:
Type Name like Count Code
Black Color 3
Black Bottle 2
Blue Color 1
Blue Bottle 1
... and so on for unpredictable and randomized thousands of names containing a similar sequence of characters.
So far, any attempt was unsuccessfully. Any clue ?
To accomplish what you want I think you either need a lookup table from which you can match the names (a table holding synonyms), or you could hard code the logic like this:
SELECT
type AS "Type",
CASE
WHEN name LIKE '%Color%' THEN 'Color'
WHEN name LIKE '%Bottle%' THEN 'Bottle'
END AS "Name",
COUNT(DISTINCT code) AS "Count Code"
FROM your_table
GROUP BY
type,
CASE
WHEN name LIKE '%Color%' THEN 'Color'
WHEN name LIKE '%Bottle%' THEN 'Bottle'
END
ORDER BY type
This would give you the result you want, as seen in this SQL Fiddle. This is obviously not a good solution - using a lookup table would be a lot better.
Using a lookup table could be done like this:
create table lookup (k varchar(20), v varchar(30));
insert into lookup values
('Bottle','Bottle'),('Bottle','Bottles'),
('Bottle','Bottle/z'),('Bottle','Bottleneck'),
('Color','Color'),('Color','Colorless'),
('Color','Colorful'),('Color','/Color'),
('Color','Color/'),('Color','Colored');
SELECT
type AS "Type",
l.k AS "Name",
COUNT(DISTINCT code) AS "Count Code"
FROM your_table tbl
INNER JOIN lookup l on tbl.name = l.v
GROUP BY type, l.k
Sample SQL Fiddle using lookup table.
Try this.
Select distinct Type, Name, count(code) from MyTable
group by Type, Name
I have a table in mysql in this structure
table: member
| Id | Name | Lastname | Username
| --------------------------------
| 1 | Alexi| Lalas | alexi
| 2 | Jack | Louis | louis
And I have a table called member images with this structre:
table: image
| Id | MemberId | Image | Type |
|------------------------------------|
| 50 | 1 | face.jpg |Avetar |
| 51 | 1 | image.jpg |Gallery|
| 52 | 2 | main.jpg |Avetar |
| 53 | 2 | jungle.jpg |Gallery|
And I want to get this result
| Id | Name | Lastname | Username | Image1 | Image2 |
|-------------------------------------------------------|
| 1 | Alexi| Lalas | alexi |face.jpg |image.jpg |
| 2 | Jack | Louis | louis |main.jpg |jungle.jpg|
Becuase of some reasons I can't handle is on app side and I have to do it on sql side.
Imagin that I always have 2 type of images and we always have Image1 and Image2.
Any help would be appritiated.
Since they are only two types, you can use the CASE expression to do so. Something like this:
SELECT
m.Id,
m.Name,
m.LastName,
m.UserName,
MAX(CASE WHEN i.Type = 'Avetar' THEN i.Image END) AS 'Image1',
MAX(CASE WHEN i.Type ='Gallery' THEN i.Image END) AS 'Image2'
FROM member AS m
LEFT JOIN image AS i ON m.Id = i.MemberId
GROUP BY m.Id,
m.Name,
m.LastName,
m.UserName;
Note that: LEFT JOIN will include all the members from the member table even if they have no images in the image table, in this case NULL will be returned.
See it in action here:
SQL Fiddle Demo
The way to do this is via a subselect (subquery). You would subselect the first column as the image for the user withe Avetar type and the other column subselect would be for the image with the type Gallery. If you can't find a way to make User ID and Type unique in your sub table then you are going to have issues with this type of query. Keep in mind that a subselects can impact performance heavily.
http://dev.mysql.com/doc/refman/5.0/en/subqueries.html
What's the best way to perform a group by statement in a csv-like column using SQL (mySQL)?
Table Products Color
+-------------+--------------+
| Product Id | Color |
+-------------+--------------+
| 120 | Red, Blue |
| 121 | Green, Black |
| 122 | Red, Black |
+-------------+--------------+
From the table above I need to count how many times a color appears and return something like this:
+-------------+-------+
| Color | Count |
+-------------+-------+
| Red | 2 |
| Blue | 1 |
| Green | 1 |
| Black | 2 |
+-------------+-------+
Is possible to do this without normalize the database?
If you can't change your table structure, but you can create a table that lists all the colors, you could use this query:
SELECT Colors.Color, Count(*)
FROM
Products INNER JOIN Colors
ON FIND_IN_SET(Colors.Color, REPLACE(Products.Color, ' ', ''))>0
GROUP BY
Colors.Color
See it working here. Please notice that it can't be optimized because it can't make use on an index.
Sorry I couldn't think of a better way to title this. In Amazon's SimpleDB, an item can have multiple values in the same column, so it's possible to select only those items that have all of the attributes being sought.
In MySQL, let's say the following table ("Photo_Attributes") contains an unlimited number of attributes for photographs that are contained in another table ("Photos"), and that the two tables are joined by Item_Number.
And, let's say I wanted to find a hat whose color was red and size was medium, which in this case would be ITEM_ID "ABC" and not "OPQ".
+-----+----------+--------+-----------+-------+
| ID | Item_ID | Object | Attribute | Value |
+-----+----------+--------+-----------+-------+
| 1 | ABC | Hat | Color | Red |
+-----+----------+--------+-----------+-------+
| 2 | FGH | Pants | Color | Blue |
+-----+----------+--------+-----------+-------+
| 3 | FGH | Pants | Size | Large |
+-----+----------+--------+-----------+-------+
| 4 | LMN | Shirt | Color | Red |
+-----+----------+--------+-----------+-------+
| 5 | ABC | Hat | Size | Med |
+-----+----------+--------+-----------+-------+
| 6 | LMN | Shirt | Size | Med |
+-----+----------+--------+-----------+-------+
| 7 | OPQ | Hat | Color | White |
+-----+----------+--------+-----------+-------+
| 8 | OPQ | Hat | Size | Med |
+-----+----------+--------+-----------+-------+
The following query would yield no results because each row contains only one Attribute and one Value.
SELECT FROM Photo_Attributes WHERE OBJECT='hat' AND (Attribute='Color" AND
Value='Red") AND (Attribute='Size' AND Value='Med');
And, this query would produce more rows than it should (i.e., all red and all medium-sized items).
SELECT FROM Photo_Attributes WHERE OBJECT='hat' AND (Attribute='Color" AND
Value='Red") OR (Attribute='Size' AND Value='Med');
What's the best way to write this -and- is there a way to do it without using JOIN in the SELECT statement? I'm wondering the latter because the query would be programmatically generated (in nodejs) and the number of Attribute-Value pairs could range from one to several. I figure I could also use nested queries, culling from recordset, but that seems equally inefficient.
SELECT pa1.Item_ID
FROM Photo_Attributes pa1
INNER JOIN Photo_Attributes pa2
ON pa1.Item_ID = pa2.Item_ID
AND pa2.Attribute = 'Size'
AND pa2.Value = 'Med'
WHERE pa1.Object = 'Hat'
AND pa1.Attribute = 'Color'
AND pa1.value = 'Red'
Assuming no overlap in your name/value pairs (e.g., You'd never have Size/Red or Color/Med), you could probably also do something like this.
SELECT pa.Item_ID
FROM Photo_Attributes pa
WHERE pa.Object = 'Hat'
AND pa.Attribute IN ('Size', 'Color')
AND pa.Value IN ('Med', 'Red')
GROUP BY pa.Item_ID
HAVING COUNT(DISTINCT Value) = 2