Let's say I have the following table, called test:
Executing the query SELECT DISTINCT category FROM test ORDER BY category; will output:
When changing a value as follows:
…and calling the query SELECT DISTINCT category FROM test ORDER BY category; again, I'll get:
But I want to get the following instead:
Is there a way to do this in SQL? Or should I do this directly in my PHP?
You should have 3 tables here. One will hold the the categories, the other one will hold the items and the final one will hold the relations between categories and items (it is also known as associative table):
categories: id name
items: id name
categories_items: category_id item_id
Your query in this case will become:
SELECT id, name
FROM categories
ORDER BY name;
If you want to get all items from a category you could do:
SELECT id, name
FROM items
JOIN categories_items
ON items.id = categories_items.item_id
AND categories_items.category_id = 4;
You should definetely normalize your tables but if you still insist on this table structure, you can try this query:
WITH CatChar(aChar, remain) AS (
SELECT LEFT(category,1), RIGHT(category, LEN(category)-1)
FROM test WHERE LEN(category)>0
UNION ALL
SELECT LEFT(remain,1), RIGHT(remain, LEN(remain)-1) FROM CatChar
WHERE LEN(remain)>0
)
SELECT DISTINCT aChar FROM CatChar
(Assuming your all category names are just one char length, otherwise you should reorganeze LEFT(...) part to split according to your separator)
Related
I want show related items with my item by metakeywords.i insert metakeywords for each item in database and Separate them by comma for example metakeywords for one item is: key1,key2,key3,key4 now i want show related items whit metakeywords how can i do it in php?
The best way to do this is to have an Item table, a Keyword table, and an Item_Keyword table.
Like this:
Item:
id
name
field1
blah
Keyword:
id
keyword
Item_Keyword:
item_id
keyword_id
To pull all the items for a keyword, you just query the Item_Keyword table:
SELECT *
FROM Item_Keyword
JOIN Item ON Item.id = Item_Keyword.item_id
WHERE Item_Keyword.keyword_id = whatever you want
I have a reviews table that contains three ways to rate an item. The items themselves then have three columns to hold the average for each value respectively.
I could do this using three nested queries in an update query, but I feel like this is inefficient... Is there a way to update them all at once?
So far I've used this as my select query:
SELECT AVG(rating_1),AVG(rating_2),AVG(rating_3) FROM items_reviews WHERE item_id = 1
I just don't know how to use the result of that query to update an item row.
You could use an join in the UPDATE:
UPDATE items a
INNER JOIN
(
SELECT
item_id,
AVG(rating_1) AS avg1,
AVG(rating_2) AS avg2,
AVG(rating_3) AS avg3
FROM items_reviews
WHERE item_id = 1
GROUP BY item_id
) b ON a.item_id = b.item_id
SET
a.avgrating1 = b.avg1,
a.avgrating2 = b.avg2,
a.avgrating3 = b.avg3
How do I select a column value as a column name and group the results as a row.
I have a table as such:
id articleId label value
1 1 title Example title
2 1 description This is the description
3 1 author Me
4 2 title Example of another type of article
5 2 description Short description
6 2 author Someone else
Is it possible to select all of the rows and use the label as the column name and the value as the value of that column name and then group them by the article name.
So how I would like to have it returned:
articleId title description author
1 Example title This is the.. Me
2 Example of an.. Short descr.. Someone else
I'm using this for a CMS where the user can define the fields for an article so we don't have to customize the table's. This is why i'm not making the tables as the I would like to have it returned. I am also aware that I can just as easily convert the result to this in php.
-- edit --
Can this be done without knowing what labels are added? In this example im using title, description and author. But it could very well be something totally different like title, shortDescription, availableTo, techInformation, etc.. The idea is that the article's are customizable for the user without needing to change the database and query's
I figured I'd better post as an answer, even if not what OP would like to hear. What you are asking to do is to populate a query with a variable number of columns based on the distinct values within column label, all associated with articleID. Taking your specific example, the following would be the resultant query that I would most likely go to in this instance (though the example from #Devart is equally valid)
SELECT
t.id,
t.articleId,
t1.value AS title,
t2.value AS description,
t3.value AS author
FROM `tableName` t
LEFT JOIN `tablename` t1
ON t1.article_id = t.article_id AND t1.label = 'title'
LEFT JOIN `tablename` t2
ON t2.article_id = t.article_id AND t2.label = 'description'
LEFT JOIN `tablename` t3
ON t3.article_id = t.article_id AND t3.label = 'author'
Now expanding this to account for up to n labels, we get the following query (metacode included, this query will NOT execute verbatim)
SELECT DISTINCT label FROM `tableName`;
SELECT
t.id,
t.articleId
// for (i=1;i<= number of distinct labels) {
,t[i].value AS [value[i]]
// }
FROM `tableName` t
// for (i=1;i<= number of distinct labels) {
LEFT JOIN `tablename` t[i]
ON t[i].article_id = t.article_id AND t[i].label = [value[i]]
// }
;
So what you can do is one of the following.
SELECT t.* FROM tablename t and then have PHP process it as required
SELECT DISTINCT label FROM tablename and have PHP build the second query with the many LEFT JOINs (or MAX / GROUP BY logic if preferred)
Create a Stored Procedure to do the same as #2. This would most likely be more efficient than #2 however may be less efficient overall than #1.
You can use pivote table trick -
SELECT
articleId,
MAX(IF(label = 'title', value, NULL)) AS title,
MAX(IF(label = 'description', value, NULL)) AS description,
MAX(IF(label = 'author', value, NULL)) AS author
FROM
table
GROUP BY
articleId
Try below :
select t1.articleId,t1.title,t1.description,t1.author
from tablename as t1
left join (select max(articleId) as articleId
from tablename
group by articleId ) as t2
on t1.articleId=tsm.articleId where [.....]
I am doing a pretty normal routine, but having a tough time getting my output correct.
I have two tables: *ads_list* (listings) and *ads_cate* (categories).
I am currently displaying my category list like so:
SELECT id, cateName FROM ads_cate ORDER BY cateName
What I am trying to achieve: count of all items in each category in this format:
Category | Number of Ads
categoryName 56
This is my current code, and have been tweaking but getting no output in my array:
SELECT
ads_cate.id,
ads_cate.cateName, // Category Name
ads_list.id,
ads_list.COUNT(title), // Title of ad
ads_list.Category // Relational Category ID INT(11)
FROM
ads_cate,
ads_list
GROUP BY cateName
ORDER BY cateName
I am calling in all required fields and running a COUNT() on my title field (as these are unique for each ad) and then I am grouping by cateName which also seems correct.
See what this gives you. I think it is what you need.
SELECT
ads_cate.cateName, // Category Name
COUNT(ads_list.id), // Title of ad
FROM
ads_cate
INNER JOIN
ads_list
ON ads_cate.id = ads_list.category
GROUP BY cateName
ORDER BY cateName
What i want, to display rows from a table which is selected by a field from other table single value, lets say to display images from a table by last category id.
I have this type of query, but this return me all matching keys rows, if i inset LIMIT 1 then it return one row...
SELECT i.prof_image FROM profile_images i
JOIN images_cat cat ON (cat.cat_id = i.cat_id)
GROUP BY i.prof_image;
//OR LIMIT 1;
Any idea to fix this problem. (i.e. displaying the latest category images)?
This will work for your specific example.. If you need to be more selective, then please post some more details..
SELECT i.prof_image
FROM profile_images i
WHERE cat_id = (select max(cat_id) from images_cat)
SELECT * FROM table_1
LEFT JOIN table_2 ON table_1.id = table_2.id
This query will grab all things in table_2 that have the same id value.
Note that it is a LEFT JOIN - which means that if there are no matching values in table_2, it will still return the values from table_1.
What is your intent with using last()?
Hope this helps.