Fill a partially filled table MYSQL - mysql

I'm trying to fill a partially filled table in mysql, I don't know if it possible though, I couldn't find a way to do it without losing data.
Since it's always easier to explain with an example. I have something like this:
+-------+-------+----------+
| Names | total | elements |
+-------+-------+----------+
| data1 | 2 | elem1 |
| | | elem2 |
| data2 | 3 | elem3 |
| | | elem4 |
| | | elem5 |
+-------+-------+----------+
And I'm trying to get something like this :
+-------+----------+
| Names | elements |
+-------+----------+
| data1 | elem1 |
| data1 | elem2 |
| data2 | elem3 |
| data2 | elem4 |
| data2 | elem5 |
+-------+----------+
Is it possible?

You won't be able to do this nicely with just a basic query, but this is the sort of thing procedure logic can be used for.
Check out the docs on WHILE loops. What you'll want to do is loop through that table ordered by the elements column. If the Names column is set, set a variable to the value of names, and if names is empty, set the column to that variable.
The example here should get you started:
http://dev.mysql.com/doc/refman/5.0/en/while.html

Related

How does Laravel's ORM specify the sorted values for the data?

E.g:
There is a field in the table called name,
Name contains some user names, for example:
| name |
---------
| Asal |
| Codaya |
| Ostily |
| Queen |
| Qta |
| Zoo |
What do you want to achieve, for example, I am passing a value now, for example, passing Q, then the returned data, that is, all the first letters Q are in front, like this:
| name |
-------------
| Queen |
| Qta |
| Asal |
| Codaya |
| Ostily |
| Zoo |
If you pass in a Z, it becomes like this:
| name |
------------
| Zoo |
| Asal |
| Codaya |
| Ostily |
| Queen |
| Qta |
How is this requirement implemented in mysql?
I think your best option would be this in SQL:
SELECT
name
FROM
user
ORDER BY
CASE
WHEN name LIKE 'E%' THEN 1
ELSE 2
END
If you are using Doctrine as ORM, I believe CASE is not supported natively in ORDER BY (in DQL), so you would have to go with raw SQL, I guess.

Use natural sorting when querying MySQL

I have home some data in a table that looks like this.
+------+
| code |
+------+
| Z1 |
| Z2 |
| Z3 |
| Z4 |
| Z10 |
| Z11 |
| Z12 |
| Z13 |
| Z20 |
| ZA |
| ZBN |
| ZFJK |
| ZX |
+------+
Running SELECT code FROM codes returns:
+------+
| code |
+------+
| Z1 |
| Z10 |
| Z11 |
| Z12 |
| Z13 |
| Z2 |
| Z20 |
| Z3 |
| Z4 |
| ZA |
| ZBN |
| ZFJK |
| ZX |
+------+
What I like to do is to get the 3 first codes Z1, Z2 and Z3 by something like SELECT code FROM codes WHERE code >= 'Z1' LIMIT 3. This statement however returns, which is expected considering how MySQL sorts data the following data.
+------+
| code |
+------+
| Z1 |
| Z10 |
| Z11 |
+------+
After getting the 3 first codes I like to get the 3 codes following the 3 first codes. Something like this SELECT code FROM codes WHERE code > 'Z3' LIMIT 3 and then get Z4, Z10 and Z11. And after that the next 3 items Z12, Z13 and Z20 and so on.
I'm able to get the output naturally sorted with a procedure if I query all the items but I only want to have 3 items, following the 3 previous returned based on natural sorting. Can I achieve this in MySQL or should I just get all the data and manipulate the data in program that is querying the database?
SQLFiddle -> here
You could use an lpad in order by
SELECT code FROM codes
order by lpad(code , 8,'0')
The problem you have is that you want (as i understand it) to sort the data first by the alphabetical part and then by the numeric part so that the order you get is:
+------+
| code |
+------+
| Z1 |
| Z2 |
| Z3 |
| Z4 |
| Z10 |
| Z11 |
| Z12 |
| Z13 |
| Z20 |
| ZA |
| ZBN |
| ZFJK |
| ZX |
+------+
However, you can't do this directly in SQL as it will order the whole string as one unit of information.
So you need to split the string into two pieces but the length of the alphabetical part is variable and there is no delimiter between the two.
The first solution is to add a delimeter to the code (if you can) so that they are as follows:
+-------+
| code |
+-------+
| Z-1 |
| Z-2 |
| Z-3 |
| Z-4 |
| Z-10 |
| Z-11 |
| Z-12 |
| Z-13 |
| Z-20 |
| ZA |
| ZBN |
| ZFJK |
| ZX |
+-------+
This will allow you to split the string into two strings by finding the location of the delimiter and sort them separately.
If you can't put in a delimiter (as this is already defined) then you will need to write a function in SQL to split the two strings.
If you know that Z is one character long:
WHERE 0+MID(code, 2) > 1
ORDER BY 0+MID(code, 2)
If the alpha prefix is variable length, then the code become "too messy to do in SQL". It would be slightly easier with MariaDB, which has things like REGEXP_REPLACE().

MYSQL multi JOIN from different tables

I have multiple MYSQLI tables for multiple details and options about a touristic package.
I have package containing the main information, then I have package_option which contains unknown number of options added to the package, and there's package_images which contains the images.
I want to get all the information in one query, but it's prooving a difficult task. Let me explain.
I've used JOIN with but the problem was if the package_option had 3 options and the package_images had 6 images, the result was a 6*4 plus 1 (package) result table.
I would like a result containing all the fields, as many as they originaly are in the tables, not multiplied for each match in every table.
For example, the table I aim for looks like that:
-------------------------------------------------------------------------
| ID | name | description | price | option | image | size | explanation |
-------------------------------------------------------------------------
| 1 | test | some desc | 50 $ | opt. 1 | img1 | 30 | |
| | | | | opt. 2 | img2 | | |
| | | | | opt. 3 | img3 | | |
| | | | | | img4 | | |
| | | | | | img5 | | |
| | | | | | img6 | | |
Right now, the above table gets populated in every field, but it's multiplied, so I don't get only 6 rows, but 24.
I did a lot of JOINS, I'm not a beginer, which is even more frustrating, but it's the first time I try to do that, a select from multiple tables with different columns and unknown number of rows.
package_option and package_images looks like that:
-------------------------------------
| ID | package_id | option / image |
-------------------------------------
| 1 | 1 | opt. 1 / img 1 |
| 2 | 2 | opt. 2 / img 2 |
..... etc
so I don't know how many rows I'll have.
Thank you in advance for t

MySQL: Hundreds of tables or one big table?

I want to create a webpage where user can organize things they collect. As everyone collects something else I want to have the users create their own datamodell (with strict limitations). If two people are collection the same "things" they can share a datastructure.
My idea was to give every collection an ID and all the tables belonging to that collection will have the ID as a prefix.
Table: Collections
ID | Collection
1 | Poststamps
2 | Barbie Dolls
Table: 1_Base
ID | StampValue | StampPic
....
Table: 2_Base
ID | EAN | Pic
....
Thus I would create many tables as each user could in theory create their own collection. I could also use only one very big table and a mapping table. Example:
Table: Colleactions
ID | Collection
1 | Poststamps
2 | Barbie Dolls
Table: Mapping
fkCollection | FieldName | Mapping
1 | DoubleField1 | StampValue
1 | BlobField1 | StampPic
2 | StringField1 | EAN
2 | BlobField1 | StampPic
Table: CollectionData
fkCollection | DoubleField1 | ... | DoubleField10 | StringField1 | ... | Stringfield10 | BlobField1 | ...
1 | 30 | | | | | | ... |
2 | | | | 21312412414 | | | ... |
Any other ideas?
Thanks for your help!
From what I can see, your second way of attempting this is going to be the easiest way... your queries will be ten fold simpler to handle, and you wouldn't need to programmably create tables on the fly... so my suggestion would be to modify your second idea slightly... Just to clarify something also, A blob will slow down the query speed so I am changing the block to hold the source link to the image instead.
TABLE: Collections
ID| Collection
1 | Poststamps
2 | Barbie Dolls
Table: CollectionData
fkCollection | DataType | VALUE | FieldName |
1 | Double | 30 | StampID |
1 | String | London | StampName |
1 | ImgSrc | ../loc | StampPic |
2 | String | Ken | BarbieName |
2 | ImgSrc | ../loc | BarbiePic |

MySQL select rows where values in one field match values in another table

I have the following tables:
tbljobpost with fields job_id int, job_title varchar(50), skill_cat_id varchar(50)
tblappskills with fields app_control Int, skill_cat_id Varchar(50)
tbljobpost:
+-------------------------------------+
| job_id | job_title | skill_cat_id |
+-------------------------------------+
| 1 | Programmer | 1,2,3,4,5,6,7 |
+-------------------------------------+
tblappskills:
+-----------------------------+
| app_control | skill_cat_id |
+-----------------------------+
| 1 | 1,2,4,5,6 |
| 2 | 1,2,3,7,4 |
| 3 | 1,2,3,4,5,6,7 |
| 4 | 7,1,4,5,6,2,3 |
+-----------------------------+
How can I query or filter the tblappskills that is the same skill_cat_id separated with comma from tbljobpost?
And the result will come like this:
+-----------------------------+
| app_control | skill_cat_id |
+-----------------------------+
| 3 | 1,2,3,4,5,6,7 |
| 4 | 7,1,4,5,6,2,3 |
+-----------------------------+
Your solution does not fit first normal form
You should store skill categories in separate cells like this:
+----------------------------+
| app_control | skill_cat_id |
+----------------------------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 4 | 4 |
+----------------------------+
Then, you can easily JOIN the tables and select the rows matching the value you want. It does not matter that app-control-id appears more than once in the table. However, if you decide to put additional data to that table, you should do it in separate table to avoid redundancy, like this:
Your new table (contains detail information about app-control) is related to the table I have mentioned above as 1 : (0..N). It's hard to explain but easy to design. If you study the normal forms mentioned above, you will understand this easily.