MySQL join query for multiple matching conditions - mysql

First off, I apologise for the vague title.. I will update it to better reflect my question if anyone has a suggestion, but for not I do not know how to categorise this topic:
I have a few tables storing information for some device. The tables are organised as shown below. The dev_prop table has some properties which are also components. Components have properties stored in the comp_prop table on the right. Other device properties like "color" do not have any more properties associated with them, just a value.
device dev_prop comp_prop
name id name value id dev_id name value id dp_id
dv1 1 comp1 aaa 1 1 height 30cm 1 1
dv2 2 comp2 bbb 2 1 height 20cm 2 2
dv3 3 color red 3 1 height 20cm 3 4
comp1 ccc 4 2 weight 300g 4 2
comp2 aaa 5 2 weight 250g 5 4
color blue 6 2 weight 99g 6 1
color pink 7 3
I want to query the database to select all components that have height 20cm, but I also want to get their weight properties in a separate row. All rows I retrieve should have one comp_prop.value, and only one.
In the sample data above, this would apply to dev_props with id's 2 and 4, because these have heights of 20cm. I would like 4 rows return then, two for their heights, and other two for their weights.
For example, I would like to retrieve rows like this:
select device.name, dev_prop.name, dev_prop.value, dev_prop.id,
comp_prop.name, comp_prop.value from comp_prop
inner join dev_prop on comp_prop.dp_id=dev_prop.id and ......
device | dev_prop.name | dev_prop.value | dev_prop.id | comp_prop.name | comp_prop.value
dv1 comp2 bbb 2 height 20cm
dv1 comp2 bbb 2 weight 300g
dv2 comp1 ccc 4 height 20cm
dv2 comp1 ccc 4 weight 250g

Wondering if you considered nesting the query? First here's the nest:
SELECT dp_id FROM comp_prop WHERE height = '20cm'
Which would give you the dp_id of all items with certain attribute, which can be shoved into conditional like so:
SELECT * FROM comp_prop WHERE dp_id IN (...)
And then just join the other three tables together

Related

Update, set a field value relative to subset of rows

I'm adding a new column position to a table. This column should hold a unique value within all rows with the same userId. It doesn't really matter if they're ordered by id, creation or just randomly. For instance:
id userId time subn position created
1 1 33 FG 1 2016-08-13
2 1 57 FG 2 2016-08-15
3 1 20 XM 3 2016-08-11
4 2 81 FG 1 2016-08-01
5 3 12 FG 1 2016-08-27
6 3 33 FG 2 2016-08-18
How can I do this? I've tried creating a copy table (so that MySQL doesn't complain of target the target table for update being specified in from), setting the initial value to 0 and running this:
UPDATE userTimes_copy uic
SET position = (SELECT 1 + MAX(uic2.position)
FROM userTimes uic2
WHERE uic.userId = uic2.userId);
But it doesn't work. The first two rows, that have the same userId, get 486 (I have 485 rows) in position, and all of the rest 1.

How to fetch children tree of given parent in B-tree

Suppose I have table called tree with id, and parent-id and data are b-tree
1
2 3
4 5 6 7 8 9
etc
all these are store in tree table like
1 - null
2 - 1
3 - 1
4 - 2
5 - 2
6 - 2
7 - 3
8 - 3
9 - 3
etc
so please write Query to fetch child tree of 2
output should be like
4 - 2
5 - 2
6 - 2
xx - 4
etc..
Select id, parent_id from tablename where parent_id = 2. Perhaps you need bottom level ones? Then you need to left join the table with itself and only return the rows that don't have children.
Edit: if the maximum number of hierarchy levels is high or unknown, you should use hierarchyid: https://msdn.microsoft.com/en-us/library/bb677213.aspx
Hope this helps!

Perform action on selected columns depending on their name

I've got a huge table, containing three "selection"-columns and many "data"-columns.
ID Thing1 Thing2 Thing3 avgData1 avgData2 highestEtc
---- -------- -------- -------- ---------- ---------- ------------
1 1 2 2 321 654 999
2 2 1 1 123 456 11
3 2 1 1 987 789 77
4 2 1 1 765 567 11
In my queries, I'm now selecting all entries with "Thing1" = x, "Thing2" = y, "Thing3" = z (Those three columns are selection-criteria.)
The purpose of getting those lines is to perform an action on each of the following data-columns: If it starts with "avg", I want to calculate an average of the specific column on all selected entries. On another prefix I want to count which number appears the most.
Is there a way of letting the MySQL Database do all this for me? I need a SQL-Statement that calculates the averages of the columns automatically, and performs other actions too.
For example, let's say I'd select the criteria Thing1=2, Thing2=1 and Thing3=1. Is there a way of writing the statement so that it returns only ONE entry, with the calculated things?
Result
----------------- ----------------- ----
(123+987+765)/3 (456+789+567)/3 11
I heard that this should be possible, and that it is a bad method of NOT letting the database perform those actions directly. Unfortunately, I have no idea how to do it.
Try this:-
SELECT ID, AVG(avgData1) AS RESULT1, AVG(avgData2) AS RESULT2, highestEtc
FROM YOUR_TAB
WHERE Thing1 = 2
AND Thing2 = 1
AND Thing3 = 1
GROUP BY ID
HAVING COUNT(highestEtc) > 1;
Hope this helps you.

Get multiple records from two tables having primary and foreign key relationship

![enter image description here][1]In the First Table tblserialnumbersprimary i have a primary field called as serialNoId ,this field is repeating multiple times in the second table tblserialnumbers. when we are inserting multiple records with that serialNoId.
I want to get Distinct records from the first table i.e tblserialnumbersprimary and corresponding multiple records from the dependent table i.e tblserialnumbers in MySQL
First Table Fields are:
tblserialnumbersprimary (serialNoId,serialPO,serialProductNo,
SerialNumberMode,serialNoAutoPrefix,serialDateOfCreation,
serialModifiedBy,serialStatus)
Second Table Fields are:
tblserialnumbers(serialId,serialNoId,
serialNo,serialNoBatchId![enter image description here][1])
I tried With This Joins Query.But its giving multiple records of first table
select * FROM tblserialnumbersprimary
LEFT OUTER JOIN tblserialnumbers
ON (tblserialnumbersprimary. serialNoId = tblserialnumbers.serialNoId )
First Table values are:
serialNoId serialPO serialProductNo SerialNumberMode serialNoAutoPrefix serialDateOfCreation serialModifiedBy serialStatus
1 PO1 PROD121 Automatic TCS-03 2/25/2014 12:00:00 AM admin 0
2 PO2 PROD345 Automatic TCS-03 2/25/2014 12:00:00 AM admin 1
3 PO5 PROD816 Automatic 2/26/2014 12:00:00 AM admin 1
4 PO1 PROD121 Automatic GTS-03 2/26/2014 12:00:00 AM admin 1
Second Table values are:
serialId serialNoId serialNo serialNoBatchId
1 1 TCS-03-PROD121-1 batch1
2 1 TCS-03-PROD121-2
3 1 TCS-03-PROD121-3 batch3
4 1 TCS-03-PROD121-4
5 1 100
6 1 101
1 2 TCS-03-PROD345-1 batch1
2 2 TCS-03-PROD345-2
3 2 TCS-03-PROD345-3 batch3
4 2 TCS-03-PROD345-4
1 3 --1
2 3 --2
3 3 --3
4 3 --4
5 3 12
6 3 13
7 3 11
1 4 -PROD816-1 batch1
2 4 -PROD816-2 batch2
1 5 GTS-03-PROD121-1 batch1
2 5 GTS-03-PROD121-2
3 5 GTS-03-PROD121-3 batch3
4 5 GTS-03-PROD121-4
Use alias and join for record in multiple table.
For i.e. `SELECT table2.id,
table1.pid,
table1.color,
table2.pname,
table2.image
FROM tbl_productcolor table1
JOIN tbl_product table2 ON table1.pid = table2.id;`
Apply your table in this way you can get all the data.

Storing data in a link table

Supoose I have the following:
tbl_options
===========
id name
1 experience
2 languages
3 hourly_rate
tbl_option_attributes
=====================
id option_id name value
1 1 beginner 1
2 1 advanced 2
3 2 english 1
4 2 french 2
5 2 spanish 3
6 3 £10 p/h 10
7 3 £20 p/h 20
tbl_user_options
================
user_id option_id value
1 1 2
1 2 1
1 2 2
1 2 3
1 3 20
In the above example tbl_user_options stores option data for the user. We can store multiple entries for some options.
Now I wish to extend this, i.e. for "languages" I want the user to be able to specify their proficiency in a language (basic/intermediate/advanced). There will also be other fields that will have extended attributes.
So my question is, can these extended attributes be stored in the same table (tbl_user_options) or do I need to create more tables? Obviously if I put in a field "language_proficiency" it won't apply to the other fields. But this way I only have one user options table to manage. What do you think?
EDIT: This is what I propose
tbl_user_options
================
user_id option_id value lang_prof
1 1 2 null
1 2 1 2
1 2 2 3
1 2 3 3
1 3 20 null
My gut instinct would be to split the User/Language/Proficiency relationship out into its own tables. Even if you kept it in the same table with your other options, you'd need to write special code to handle the language case, so you might as well use a new table structure.
Unless your data model is in constant flux, I would rather have tbl_languages and tabl_user_languages tables to store those types of data:
tbl_languages
================
lang_id name
1 English
2 French
3 Spanish
tbl_user_languages
================
user_id lang_id proficiency hourly_rate
1 1 1 20
1 2 2 10
2 2 1 15
2 2 3 20
3 3 2 10
Designing a system that is "too generic" is a Turing tarpit trap for a relational SQL database. A document-based database is better suited to arbitrary key-value stores.
Excepting certain optimisations, your database model should match your domain model as closely as possible to minimise the object-relational impedance mismatch.
This design lets you display a sensible table of user language proficiencies and hourly rates with only two inner joins:
SELECT
ul.user_id,
u.name,
l.name,
ul.proficiency,
ul.hourly_rate
FROM tbl_user_languages ul
INNER JOIN tbl_languages l
ON l.lang_id = ul.lang_id
INNER JOIN tbl_users u
ON u.user_id = ul.user_id
ORDER BY
l.name, u.hour
Optionally you can split out a list of language proficiencies into a tbl_profiencies table, where 1 == Beginner, 2 == Advanced, 3 == Expert and join it onto tbl_user_languages.
i'm thinking it's a mistake to put "languages" as an option. while reading your text it seems to me that english is an option, and it might have an attribute from option_attributes.