sql query results depend on attributes of other table - mysql

Cars:
id name
1 Mercedes
2 Audi
CarAttributes:
id car_id attribute
1 1 fast
2 1 modern
3 1 fancy
4 1 green
5 2 fast
6 2 quiet
7 2 blue
8 2 old
How would the sql query look if the returns depend on the attributes of the car like following:
[fast OR modern] AND [fancy OR old] = would return both cars
[fast OR modern] AND [old OR blue] = would only return the audi car

You can use aggregation with a having clause:
select car_id
from carattributes
group by car_id
having sum( attribute in ('fast', 'modern')) > 0 and
sum( attribute in ('fancy', old')) > 0

Related

mySQL - Select records based on value in order, then random records in one query

I'm looking to have one mySQL query where I can select all records set to a particular value, then selecting a number of other records from the records left, in a random order.
To explain, here's an example: (MyTable database table)
ID Name SomeValue
1 Fred 0
2 Jake 0
3 Jone 1
4 Bill 0
5 Greg 0
6 Thom 2
7 Jane 3
8 Erin 0
So first, I'd want to select all records where SomeValue is more than 0. The appropriate mySQL query for this would be:
SELECT * FROM MyTable WHERE SomeValue > 0 ORDER BY SomeValue DESC
This would return:
7 Jane 3
6 Thom 2
3 Jone 1
Next (in the same query), how would it be possible to select 3 other records at random (limit 6), from the ones remaining?
So that the end result of records returned looks something like this:
7 Jane 3
6 Thom 2
3 Jone 1
5 Greg 0 // Randomly picked
1 Fred 0 // Randomly picked
8 Erin 0 // Randomly picked
Use union all:
(select t.*
from t
where somevalue > 0
) union all
(select t.*
from t
where somevalue = 0
order by rand()
limit 3
);
If you want the values ordered by somevalue add order by somevalue as the last line of the query.

MySQL multiplication

I am trying to do a multiplication operation in MySQL.
I have the following table called vehicul:
id car_type car_model number price car_id
1 audi <model1> 2 320 1
2 audi <model2> 4 100 1
3 bmw <model1> 3 240 2
4 bmw <model2> 6 500 2
5 bmw <model3> 1 400 2
I have this command:
SELECT car_type, sum(price) FROM vehicul as v, GROUP BY marca
Which displays the following:
car_type price
audi 420
bmw 1140
But what I want is to display the number * price and the result to be:
car_type price
audi 1040
bmw 4120
Basically.. sum(number*price).. how can I do that? I have tried doing:
SELECT car_type, sum(price*number) FROM vehicul as v, GROUP BY marca
But I am getting:
#1052 - Column 'number' in field list is ambiguous
select car_type, sum(price*number) as price from vehicul group by car_type..
http://sqlfiddle.com/#!2/3d881/1
you should use sum(field_1*field_2) instead of sum()*sum()
Your query is totally correct. You may have more than 1 table which contain 2 or more number column. Try:
SELECT car_type, sum(price)*sum(number)
FROM vehicul
GROUP BY marca;
But with the logic you will need this to get total price:
SELECT car_type, sum(price*number)
FROM vehicul
GROUP BY marca;

better alternative for this complex mysql query

I have two tables
1.fw_respondent_answers
2.fw_question_options
the structures are:
fw_respondent_answers
id invitationid qdetailid optionid
1 2 1 1
2 2 2 2
3 2 3 3
4 3 1 4
5 3 2 5
6 3 3 6
fw_question_options:
id optionname qdetailid
1 india 1
2 teacher 2
3 ok 3
4 france 1
5 assistane 2
6 good 3
Desired Output:
invitationid country profession answer
2 india teacher ok
3 france assistant good
Explanation:i want to get the optionname associated with a particular invitationid corresponding to the qdetailid and optionid.
optionid is the primary key of fw_question_options(id).
what i have tried:
SELECT distinct fra.`invitationid` ,fo.optionname as country,
fo1.optionname as profession,fo2.optionname as nps
FROM `fw_respondent_answers` fra,fw_question_options fo,
`fw_respondent_answers` fra1,fw_question_options fo1,
`fw_respondent_answers` fra2,fw_question_options fo2
WHERE fra.`optionid`=fo.id and fra.`qdetailid`=2
and fra1.`optionid`=fo1.id and fra1.`qdetailid`=1
and fra2.`optionid`=fo2.id and fra2.`qdetailid`=3
Question:my above query is very slow.i just want to know is there any other better alternative to the above query?
Thanks in advance.
Try this:
SELECT a.invitationid,
MAX(IF(a.qdetailid = 1, b.optionname, '')) AS country,
MAX(IF(a.qdetailid = 2, b.optionname, '')) AS profession,
MAX(IF(a.qdetailid = 3, b.optionname, '')) AS nps
FROM fw_respondent_answers a
INNER JOIN fw_question_options b ON a.optionid = b.id
GROUP BY a.invitationid

Group by only for "limit and offset" in MySQL

Whilst trying to do pagination I've run into this problem.
My table-
ID CarBrand Car Model
---------------------------
1 Alfa Romeo Guilietta
2 Alfa Romeo Mito
3 Audi A3
4 Audi R8
5 Audi TT
6 Fiat Punto
7 Fiat Panda
8 Ford Mondeo
9 Ford Mustang
10 Nissan Almera
11 Nissan Note
12 Nissan Qashqai
13 Toyota Aygo
14 Toyota Prius
15 Volkswagen Beetle
16 Volkswagen Golf
17 Volkswagen Polo
18 Volkswagen Up
I have the data displayed like so, in groups of two:
-Fiat - Punto
Panda
-Ford - Mondeo
Mustang
So there are 2 brands but 4 database results.
Is it possible to have a query limit and offset my results to two brands while showing all the models for the brand?
Sorry if I'm not clear!
It is clear. Try this:
select * from t t1
join (
select distinct carBrand from t
limit 2
) s on t1.carBrand = s.carBrand
Before the limit 2 apply the ordering you want.
To get a limit, without using the limit keyword, you can impose a count.
For example, given the table definition
create table cars (id int,
carBrand char(10),
carModel char(10));
this will give you all the Car Models for the top 2 Car Brands
select cars.carBrand, cars.carModel
from cars
where ((select count(*) from
(select distinct carBrand from cars) as carBrands
where carBrands.carBrand < cars.carBrand) < 2)
order by cars.carBrand, cars.carModel;
This creates an inline table just listing the carBrands and then joins this back to cars to get the list of all cars that are in the top 2 brands. The count(*) .... < 2 enforces the limit. Consider 'Ford', for example, in your above data. In 'Ford''s case, there are 3 brands that are < 'Ford' alphabetically, so the count(*) above = 3. Since 3 is not less than 2, no 'Ford' cars appear in the output.
The output on your test data would be:
CARBRAND CARMODEL
Alfa Romeo Guilietta
Alfa Romeo Mito
Audi A3
Audi R8
Audi TT
Now, you didn't say how you wanted to pick the 2 brands -- you just listed Ford and Fiat in your example -- I don't know how you happened to pick those. If you want something other than alphabetical criteria for ordering, that's doable, but harder.
SQL Fiddle and results for all this: http://sqlfiddle.com/#!2/33a8f/3
It's a matter of database design. Maybe you should split your data into two tables model (model names) and brand (brand names). Then you can write a query like this:
SELECT m.name, b.name
FROM model m
INNER JOIN brand b
WHERE b.id IN (
SELECT id
FROM brand
ORDER BY name ASC
LIMIT 2 OFFSET 0
)
I did not test the code. No need for GROUP BY in my opinion.

MySQL -- Retrieve rows with specific field condition but with a fallback field condition

Suppose we have these 3 tables,
Language
language_id name
1 English
2 Tagalog
Color
color_id
1
2
3
4
Color translations
color_translations_id color_id language_id name
1 1 1 Black
2 2 1 White
3 3 1 Red
4 4 1 Blue
5 1 2 Itim
6 2 2 Puti
Suppose I want to get all color translations rows for each color which are in Tagalog but with a fallback language in English. The result should be
color_translations_id color_id language_id name
5 1 2 Itim
6 2 2 Puti
3 3 1 Red
4 4 1 Blue
Furthermore, if the translation table is like this
color_translations_id color_id language_id name
1 1 1 Black
2 2 1 White
3 3 1 Red
4 4 1 Blue
Even if there are no Tagalog rows, I should return all 4 of them since my fallback language is in English
Is there a way to do this in SQL?
This was written for SQL Server and I had to change the names a bit, but the idea is there and I didn't use any proprietary features, so it should work. You may need to change the INNER JOINs to just JOINs.
WITH PrimaryLanguageColors AS
(SELECT color_id, color_translations_id
FROM ColorTranslations INNER JOIN Languages
ON ColorTranslations.language_id = Languages.language_id
WHERE Languages.Name = 'Tagalog')
SELECT color_translations_id, color_id, ColorTranslations.language_id,
ColorTranslations.name
FROM ColorTranslations INNER JOIN Languages
ON ColorTranslations.language_id = Languages.language_id
WHERE color_translations_id IN (SELECT color_translations_id
FROM PrimaryLanguageColors)
OR (color_id NOT IN (SELECT color_id FROM PrimaryLanguageColors)
AND Languages.Name = 'English')