I would like to get all information about every item. Items has global variable (here on_stock), but every item has also its own property in different table, and that table has the same name as the items type name.
select items
join its type_id on types table id -> name
join selected item on name.id
Here is the sample:
[items]
id | on_stock | type_id
-----+----------+-----------
1 1 1(=car)
2 0 1(=car)
3 1 2(=ship)
4 0 2(=ship)
[types]
id | name
----+--------
1 car
2 ship
[car]
id | top_speed
----+-----------
1 200
2 300
[ship]
id | color
-----+-------
3 red
4 blue
expected result:
1 on_stock=1 top_speed=200
2 on_stock=0 top_speed=300
3 on_stock=1 color=red
4 on_stock=0 color=blue
Please help to achieve this!
If I could not do it in one request, I'll do it in more(1+item types count).
first, I need the required types as array(id=>name):
$req_types = array();
$rs = mysql_query("
SELECT items.type_id,types.name
FROM items
JOIN types ON items.type_id=type.id
GROUP BY items.type_id
");
while($type= mysql_fetch_assoc($rs))
$req_types[$type['id']] = $type['name'];
then I need the common and individual item data:
$groups = array();
foreach($req_types as $table)
{
$rs = mysql_query("
SELECT items.*,$table.*
FROM items
JOIN $table ON $table.id=items.id
");
while($item = mysql_fetch_assoc($rs))
$groups[$table][] = $item;
}
It isn't pretty, but neither is the data structure. Here is a query to do what you want
SELECT I.id, I.On_stock, C.top_speed,S.Color
FROM ITEMS I
LEFT JOIN Car C ON (I.ID = C.CarID)
LEFT JOIN Ship S ON (I.ID = S.ShipID)
You will have to tweak the query every time you add a new item type, but that is just a downside of this data structure.
Related
product_options
ID | Option
1 | One
2 | Two
3 | Three
product_to_options
ID | Product | Option
1 | 1 | 1
2 | 2 | 2
3 | 2 | 3
Essentially, I need to get all the rows from product_options, apart from the
ones that are supplied where the options are on the same products.
For example:
Passing the value of 1, would return nothing.
Passing the value of 2, would return the option with ID 3
Passing the value of 3, would return the option with ID 2.
I did my best with what I understand.
pto.Product = #option so you get all the rows match #option
pto.Option <> #option but filter those with the same ID
.
SELECT po.*
FROM product_options po
JOIN (
SELECT pto.Option
FROM product_to_options pto
WHERE pto.Product = #option
AND pto.Option <> #option
) as filter
ON PO.ID = filter.Option
You can join a table to itself, filter the left table on the value and return the value from the right table.
SELECT
pto2.Option
FROM
product_to_options pto1
INNER JOIN product_to_options pto2
ON pto1.Product = pto2.Product
AND pto1.ID <> pto2.ID
WHERE
pto1.option = #option;
You should note that you can get more than one value back depending on the data.
Here's a working sample with minor syntax changes for sql server (you'll need to check text-only-results or click through the grid)
I am trying to apply a conditional condition inside ON clause of a LEFT JOIN. What I am trying to achieve is somewhat like this:
Pseudo Code
SELECT * FROM item AS i
LEFT JOIN sales AS s ON i.sku = s.item_no
AND (some condition)
AND (
IF (s.type = 0 AND s.code = 'me')
ELSEIF (s.type = 1 AND s.code = 'my-group')
ELSEIF (s.type = 2)
)
I want the query to return the row, if it matches any one of the conditions (Edit: and if it matches one, should omit the rest for the same item).
Sample Data
Sales
item_no | type | code | price
1 0 me 10
1 1 my-group 12
1 2 14
2 1 my-group 20
2 2 22
3 2 30
4 0 not-me 40
I want the query to return
item_no | type | code | price
1 0 me 10
2 1 my-group 20
3 2 30
Edit: The sales is table is used to apply special prices for individual users, user groups, and/or all users.
if type = 0, code contains username. (for a single user)
if type = 1, code contains user-group. (for users in a group)
if type = 2, code contains empty-string (for all users).
Use the following SQL (assumed, the the table sales has a unique id field as usual in yii):
SELECT * FROM item AS i
LEFT JOIN sales AS s ON i.sku = s.item_no
AND id = (
SELECT id FROM sales
WHERE item_no = i.sku
AND (type = 0 AND code = 'me' OR
type = 1 AND code = 'my-group' OR
type = 2)
ORDER BY type
LIMIT 1
)
Try following -
SELECT *,SUBSTRING_INDEX(GROUP_CONCAT(s.type ORDER BY s.type),','1) AS `type`, SUBSTRING_INDEX(GROUP_CONCAT(s.code ORDER BY s.type),','1) AS `code`,SUBSTRING_INDEX(GROUP_CONCAT(s.price ORDER BY s.type),','1) AS `price`
FROM item AS i
LEFT JOIN sales AS s
ON i.sku = s.item_no AND (SOME CONDITION)
GROUP BY i.sku
I have this schema:
items | taxonomy | subjects
| |
ID headline | item_id subject_id | subject_id subject
-------------------------------------------------------------------------
1 information | 1 1 | 1 cities
2 here we are | 2 1 | 2 towns
3 more things | 3 2 | 3 water
4 doo dah | 3 4 | 4 telephones
| 4 1 |
| 4 3 |
I would like to select a single row from "items" and with it, include all the rows from "subjects" which are joined by the "taxonomy" table. So for example, getting item.ID=3 would result in something like:
items.ID = 3
items.headline = "more things"
subjects.subject = "towns"
subjects.subject = "telephones"
I've started with this query
SELECT
i.ID,
i.headline,
s.subject_name
FROM items i
JOIN taxonomy t
on i.ID=t.item_id
JOIN subjects s
on t.subject_id=s.subject_id
WHERE i.ID = 3
But this only returns a single value from subject_name even if there are multiple values associated with that item_id.
EDIT
I actually had a LIMIT 1 on the query which was causing (as #Gordon Linoff said) only one row to be returned, even though there were multiple rows in the result set corresponding to the multiple subjects. His solution still does nicely, because I only want to return a single row.
Your query returns the subjects on multiple rows. If you want the subjects on a single row, then you need some form of concatenation:
SELECT i.ID, i.headline, GROUP_CONCAT(s.subject_name) as subjects
FROM items i JOIN
taxonomy t
ON i.ID = t.item_id JOIN
subjects s
ON t.subject_id = s.subject_id
WHERE i.ID = 3
GROUP BY i.ID, i.headline;
For one item, the GROUP BY is optional, but it is good form in case you modify the query to handle multiple items.
I would suggest you the "union all" clause (or "union", if you are not needing the duplicates).
(SELECT
"taxonomy" As Name,
i.headline As Value
FROM items i
JOIN taxonomy t
on i.ID=t.item_id
WHERE i.ID = 3)
Union All
(SELECT
"subject" As Name,
s.subject_name As Value
FROM items i
JOIN subjects s
on t.subject_id=s.subject_id
WHERE i.ID = 3)
You can add a 2nd field in each select to indicate type of item selected ("headline", "subjects", etc).
How do I pull a list of users who only have new items?
I tried this query . . . SELECT * FROM items where status = 'new' GROUP BY item_owner;
but mike shows up in the output cause he has a new car also, but I only want users with exclusively new cars.
Table 1
------------------------------------------------------------
Table: User_Profiles
Id username
1 mike
2 jim
Table 2
------------------------------------------------------------
Table: Items
Id item status item_owner
1 car new mike
2 car old mike
3 car new jim
4 car new jim
I tried this query . . . SELECT * FROM items where status = 'new' GROUP BY item_owner;
but mike show mike is in the output cause he has a new car also, but I only want users with exclusively new cars.
Here's one way: count both old and new, then include anyone with (a) one or more new and (b) zero old:
SELECT item_owner
FROM Items
GROUP BY item_owner
HAVING COUNT(CASE WHEN status = 'new' THEN 1 END) > 0
AND COUNT(CASE WHEN status = 'old' THEN 1 END) = 0
Here is a revised SQL fiddle http://sqlfiddle.com/#!2/038e7/4
The key is to exclude all owners who have any status other than 'new'
SELECT DISTINCT i.item_owner
FROM items i
where not exists (select 1
from items i2
where i2.item_owner = i.item_owner
and i2.status <> 'new')
I'm listing product properties in a MySQL table where each row contains a product ID prod and a property ID prop. If a product has three properties, this results in three rows for that product. Example table:
prod | prop
-----+-----
1 | 1
2 | 1
2 | 2
2 | 3
3 | 2
3 | 4
How can I find which products have both properties #1 and #2 (product #2)?
The only way that I can think of is one select and inner join per property, but I think that would be very inefficient. It's a search function for a website and has to work for 10k lines in the table and 10 requested properties.
SELECT prod
FROM tbl
WHERE prop IN (1, 2)
GROUP BY prod
HAVING COUNT(*) = 2
And if there will be always 2 properties to find - then INNER JOIN would be a bit more efficient:
SELECT t1.p
FROM tbl t1
INNER JOIN tbl.t2 ON t2.prod = t1.prod
AND t2.prop = 2
WHERE t1.prop = 1
The recommended index for this query to be efficient as much as possible is a compound one (prop, prod)