I have a table as follows, it has an ID and item name,order and type.
+--------+----------------+-----------+---------+
| ID | ITEM | ORDER | TYPE |
+--------+----------------+-----------+---------+
| 1 | Banana | 2 | Fruit |
+--------+----------------+-----------+---------+
| 2 | Apple | 1 | Fruit |
+--------+----------------+-----------+---------+
| 3 | Orange | 4 | Fruit |
+--------+----------------+-----------+---------+
| 4 | Lemon | 3 | Fruit |
+--------+----------------+-----------+---------+
If I were to delete say Lemon the ORDER would be 1,2,4. Is there a method to reindex the remaining items to get the following result?
+--------+----------------+-----------+---------+
| ID | ITEM | ORDER | TYPE |
+--------+----------------+-----------+---------+
| 1 | Banana | 2 | Fruit |
+--------+----------------+-----------+---------+
| 2 | Apple | 1 | Fruit |
+--------+----------------+-----------+---------+
| 3 | Orange | 3 | Fruit |
+--------+----------------+-----------+---------+
Right before you delete the Lemon row - check what its ORDER column value is.
After that perform
UPDATE tbl SET `ORDER` = `ORDER` - 1 WHERE `ORDER` > value_lemon_had
There's no way to do this completely automatically, but it would be fairly simple to do. Assuming that ORDER is not unique it's easier, but if it is you would have to retrieve the ORDER of "Lemon" first. Then, just do:
UPDATE Fruit SET ORDER = ORDER - 1 WHERE ORDER > ?
Where ? is Lemon's ORDER.
Assuming ORDER is not unique, then you could just do this query beforehand, but you would join on Fruit selecting Lemon's order to replace ?.
Related
I have this table:
table 1
+----+-----------------------+----------+------+-------+
| ID | COUNTRY | QUANTITY | EACH | PRICE |
+----+-----------------------+----------+------+-------+
| 1 | U.S.A | 1 | 12 | 1*12 |
| 2 | U.K. | 2 | 3 | 2* 3 |
| 3 | GERMANY | NULL | 3 | |
| 4 | FRANCE;GERMANY; U.S.A | 0 | 7 | |
| 5 | U.S.A;GERMANY | 3 | 8 | 3*8 |
| 6 | FRANCE;U.K. | 1 | 10 | 1*10 |
| 7 | U.S.A;FRANCE | 2 | 6 | 2*6 |
| 8 | FRANCE;FRANCE | 9 | 3 | 9*3 |
+----+-----------------------+----------+------+-------+
and this code sql:
SELECT
COUNTRY,
SUM(COALESCE(IF(QUANTITY = NULL OR QUANTITY = 0,1,QUANTITY), 1) * EACH) AS PRICE
FROM table1
GROUP BY COUNTRY
How could I make unique values for the country column and return: USA = 48 (ID: 1+5+7); UK= 6; GERMANY=3; FRANCE = 44 (ID: 4+6+8). I want that the rows, those contain two, three, four countries to be eliminated and to remain only the first country from row.
Thank you!
Use substring_index to get the first country in the ;-separated list.
SELECT
SUBSTRING_INDEX(COUNTRY, ';', 1) AS COUNTRY
SUM(IF(QUANTITY IS NULL OR QUANTITY = 0,1,QUANTITY) * EACH) AS PRICE
FROM table1
GROUP BY COUNTRY
It would be much more complicated if you wanted to keep all the rows where each country appears (in that case I would recommend doing it in PHP, not MySQL, since MySQL doesn't have a builtin way to do explode()).
I am trying to figure out how to select an item from table by his column name p.e.
strucutre looks like this
table items
id | name | column_1 | column_2 | column_3 |
1 | nm1 | 1 | 4 | 7,8 |
2 | nm2 | 2,3 | 4 | 9 |
3 | nm3 | 3,1 | 4 | 7 |
table columns
id | c_name |
1 | cnm1 |
2 | cnm2 |
3 | cnm3 |
table column_values
id | c_id | value |
1 | 1 | abcd |
2 | 1 | cdbh |
3 | 1 | dsff |
4 | 2 | wewe |
5 | 2 | cgbh |
6 | 2 | cdlh |
7 | 3 | adbh |
8 | 3 | qdbh |
9 | 3 | pdbh |
So when I wanted to find "abcd" I tried
"SELECT a.* FROM items a, columns b, column_values c WHERE c.`value` LIKE '%abcd%' GROUP BY a.`id`"
but I knew this will find nothing without any conections so i went further
"SELECT a.* FROM items a, columns b, column_values c WHERE c.`value` LIKE '%abcd%' AND b.`id` = c.`c_id` GROUP BY a.`id`"
still no proper connection with item
and here is the problem there is a changing amount of columns and the name contains id of the column and value is set of ids of column values.
So i need to select item by his name which is "name+"column_id in column_values by FIND IN SET cause if i look for abcd it is id 1 and there are two items which have id 1 in column_1
item 1 and item 2
ALSO id of values are AI so there is not possibility of duplicate so there is no need to check of column_id to search in proper column in item table
it can work something like for from 0 - 30 p.e. and it will search in column_1, column_2 column_3 until 30 for id match
My SQL table looks like
+-----+------------+--------------+--------------+-----------+------------+-----------+
| rid | ship_to_id | product_code | product_name | first_row | second_row | third_row |
+-----+------------+--------------+--------------+-----------+------------+-----------+
| 1 | 555 | A | Crystal | 1 | 2 | 3 |
| 1 | 555 | A | Crystal | 4 | 5 | 6 |
| 2 | 333 | B | Diamond | first | second | third |
| 2 | 333 | A | Crystal | ROW 1 | ROW 2 | ROW 3 |
| 2 | 333 | A | Crystal | ROW 4 | ROW 5 | ROW 6 |
+-----+------------+--------------+--------------+-----------+------------+-----------+
And I am trying to get following results
+-----+------------+--------------+-------------------------------------+
| rid | ship_to_id | product_name | data |
+-----+------------+--------------+-------------------------------------+
| 1 | 555 | Crystal | 1 2 3 4 5 6 |
| 2 | 333 | Diamond | first second third |
| 2 | 333 | Crystal | ROW 1 ROW 2 ROW 3 ROW 4 ROW 5 ROW 6 |
+-----+------------+--------------+-------------------------------------+
Can someone please tell me what is wrong with my code. Thanks
$query = mysql_query("SELECT * FROM mytable group by rid, ship_to_id, product_code, product_name");
while($row = mysql_fetch_array($query)) {
echo "$row[rid] $row[ship_to_id] $row[product_code] $row[product_name] $row[first_row] $row[second_row] $row[third_row] <br>";
}
You're forgetting product_code sometimes, I guess.
This probably is bad database design. You should learn about Database normalization and related techniques.
Third, SQL normally produces the same number of columns for every result record, so the best result you could have has rows like 1, 555, "A", "Crystal", "1 4 2 5 3 6" (notice these are 5 values). But I cannot think of a concatenation method that would produce the numbers in the 1 2 3 4 5 6 order. Depending on the better form of your database-schema-to-be, this might be something easier done in PHP than SQL.
If you're still up to concatenating all values into a single cell (as in the newly formatted example output), the you should try something along these lines:
SELECT
rid, ship_to_id, product_code, product_name,
GROUP_CONCAT(CONCAT(first_row,'#',second_row,'#',third_row) SEPARATOR '~') AS data
FROM tablename
GROUP BY rid, ship_to_id, product_code, product_name;
Notice that the values of first_row etc. are separated by a '#' and the values from distinct records by a '~' sign. You can find more options in the documentation of MySQL's GROUP_CONCAT().
you can try something like
select rid,ship_to_id,product_name,
GROUP_CONCAT(CONCAT(first_row,' ',second_row,' ',third_row) as new_val
from mytable
group by rid,ship_to_id,product_name;
As you group by the first 4 columns and use no aggregation function on the remaining ones, data will be lost when multiple record have the same values in the columns grouped by.
So basically the result will be like the following:
+-----+------------+--------------+------------------------------------+
| rid | ship_to_id | product_name | first_row | second_row | thrid_row |
+-----+------------+--------------+------------------------------------+
| 1 | 555 | Crystal | 1 | 2 | 3 |
| 2 | 333 | Diamond | first | second | third |
| 2 | 333 | Crystal | ROW 1 | ROW 2 | ROW 3 |
+-----+------------+--------------+------------------------------------+
That's what group by means. To keep the data of the fields containing varying data, you must use an aggregation function on them, like GROUP_CONCAT. Example:
SELECT rid, ship_to_id, product_code, product_name, GROUP_CONCAT(first_row), GROUP_CONCAT(second_row), GROUP_CONCAT(third_row)
FROM mytable
GROUP BY rid, ship_to_id, product_code, product_name
This will concatenate the values of the corresponding record like this:
+-----+------------+--------------+------------------------------------------+
| rid | ship_to_id | product_name | first_row | second_row | thrid_row |
+-----+------------+--------------+------------------------------------------+
| 1 | 555 | Crystal | 1 4 | 2 5 | 3 6 |
| 2 | 333 | Diamond | first | second | third |
| 2 | 333 | Crystal | ROW 1 ROW 4 | ROW 2 ROW 5 | ROW 3 ROW 6 |
+-----+------------+--------------+------------------------------------------+
However, your approach with GROUP BY is probably not be the best for this case. It would worth to think about to just order by the rid, ship_to_id, product_code, product_name columns, and then iterate through them in PHP with the given order and merge the corresponding rows there.
You may also have to reconsider you database design, as a query like this smells about a bad concept :)
I have a database with rows of "parents" and "children". Similar entries, but one entry is generic version of the more specific child. However, I want these entries to match exactly in certain columns.
Here's an example of my database:
| ID | IsChildOfID | Food | Type |
| 1 | | | Fruit |
| 2 | 1 | Apple | Fruit |
| 3 | 1 | Pear | Vegetable |
| 4 | 1 | Banana | Vegetable |
| 5 | | | Vegetable |
| 6 | 5 | Lettuce | Fruit |
| 7 | 5 | Celery | Vegetable |
| 8 | 5 | Cabbage | Fruit |
In this example there are 2 parents and 6 children. The value of "type" field is inconstant with some of the children. I want to be able to find any children in the database and replace it with their parent's value in only some of the columns. Is this possible with purely MySQL or do I need do it with php? Thanks.
UPDATE name_of_table SET Type = "Fruit" WHERE IsChildOfID = 1
and
UPDATE name_of_table SET Type = "Vegetable" WHERE IsChildOfID = 5
But if you want to do it dynamicaly please use php or some other language...
Also I would prefer to use 2 tables for this kind of data...
Generally, when you use parent/children relationships in sql, you should make two separate database tables for each. In your case, you should create a database entitled "types" and include a type_id for each element in the child table.
Example
Child table:
| ID | TYPE_ID | Food |
| 2 | 1 | Apple |
| 3 | 2 | Pear |
| 4 | 2 | Banana |
| 6 | 1 | Lettuce |
| 7 | 2 | Celery |
| 8 | 1 | Cabbage |
Type table:
| ID | Type |
| 1 | Fruit |
| 2 | Vegetable |
You can then reference it by looping through the type table, and using a sql statement like
$types = mysql_query ( 'SELECT * FROM type_table');
WHILE ( $type = mysql_fetch_array ( $types ) )
{
$sql = 'SELECT * FROM child_table WHERE TYPE_ID = "' . $type['type'] . '"';
}
Similar answer here:
UPDATE multiple tables in MySQL using LEFT JOIN
I was going to write this:
UPDATE foods c
JOIN foods p ON p.id = c.IsChildOfId
SET c.type = p.type
WHERE p.isChildOfId IS NULL
But then upon further reading of the link above, not sure you can reference the target table. Worth a try.
I have a table connected to another table through foreign key;
First Table is the brand; it has a brand_id and brand_name fields
Second Table is the Product Line; it has a Line_id and line_name fields
Third Table is the Lines Offered; it has a id, Brand (which is a foreign key from the first table), and Line_name (which is a foreign key from the second table.
If i will look into the third table on mysql the fields contains the id numbers of the foreign keys.
My question is this, is it possible that the stored value will be the name itself and not the ID? or Is it possible to add a field on my third table named it as Brand_name which is a VARCHAR that will display the exact brand name from the first table. Example the values of my third table would be '1','3','The Brand Name of brand with id no. 3','25'; - If yes i dont have any idea how to do this.
Nothing is preventing you from doing this. You would simply add a brand_name field to the "third table"... The question begging to be asked is: why do you want to do this?
brands
_________________________
| brand_id | brand_name |
| 1 | brand1 |
| 2 | brand2 |
| 3 | brand3 |
| 4 | brand4 |
| 5 | brand5 |
-------------------------
lines
_________________________
| line_id | line_name |
| 1 | line1 |
| 2 | line2 |
| 3 | line3 |
| 4 | line4 |
| 5 | line5 |
-------------------------
linked
_________________________________________________
| id | line_id | brand_id | brand_name |
| 1 | 5 | 1 | brand1 |
| 2 | 5 | 2 | brand2 |
| 3 | 4 | 2 | brand2 |
| 4 | 4 | 3 | brand3 |
| 5 | 4 | 3 | brand3 |
| 6 | 3 | 4 | brand4 |
| 7 | 3 | 4 | brand4 |
| 8 | 2 | 4 | brand4 |
| 9 | 2 | 5 | brand5 |
| 10 | 1 | 5 | brand5 |
------------------------------------------------
That's your proposed setup. Now if we:
SELECT brand_id, brand_name FROM linked WHERE line_id = 4;
We would get:
_________________________
| brand_id | brand_name |
| 2 | brand2 |
| 3 | brand3 |
| 3 | brand3 |
-------------------------
But the same could be achieved without duplicate data (in large databases it's pretty unreasonable to have duplicate data like that), and without needing to update BOTH the linked and brand tables every time the brand name changes by using:
SELECT linked.brand_id, brands.brand_name
FROM brands, linked
WHERE linked.line_id = 4 AND brands.brand_id = linked.brand_id;
_________________________
| brand_id | brand_name |
| 2 | brand2 |
| 3 | brand3 |
| 3 | brand3 |
-------------------------
That answer didn't need to be that long. I was having fun making tables.