MySQL - PHP unique values from rows - php

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()).

Related

MYSQL OR SQL SELECT with both COMPARE (HAVING) and GROUP

I have three tables in a database and want to sum and compare in one SELECT statement.
The logic is that if one article runs low in stock it should be selected. An article runs low if the summarized quantity of all rows with the same artID in the table Articles in stock (an article can have several rows in the table and therefore needs to be summarized) is lower or equal to the column warning in the row with the corresponding ID. This is also warehouse specific, meaning that an article can be fully stocked in one warehouse, and at the same time running low in another. Which is why it is needed to summarize grouped on a specific warehouse.
Information about which warehouse is running low, and such as artNr for the article is also needed, which can be found in table Articles
Articles
+----+-------+---------+
| ID | artNr | warning |
+----+-------+---------+
| 1 | LA08 | 5 |
| 2 | LA09 | 10 |
| 3 | LA58 | 0 |
+----+-------+---------+
warehouse
+----+-------+
| ID | artID |
+----+-------+
| 3 | 1 |
| 4 | 1 |
| 5 | 2 |
+----+-------+
Articles in stock
+----+-------+-------------+----------+
| ID | artID | warehouseID | quantity |
+----+-------+-------------+----------+
| 1 | 1 | 3 | 10 |
| 2 | 1 | 5 | 15 |
| 3 | 2 | 5 | 45 |
| 4 | 1 | 3 | 20 |
| 5 | 3 | 5 | 4 |
+----+-------+-------------+----------+
select a.id, s.warehouseID, sum(s.quantity)
from articles a
join articles_in_stock s on a.id = s.artID
group by a.id, s.warehouseID
having sum(s.quantity) <= a.warning

MySQL group rows by one column sorting by another column

I'm developing a PHP script, and I have the following table:
+----+-----------+----------+--------------+
| id | id_parent | position | feature |
+----+------------+---------+--------------+
| 1 | 1 | 2 | -B-A-C- |
| 2 | 1 | 3 | -B-C- |
| 3 | 2 | 4 | -C-B- |
| 4 | 3 | 1 | -A-B- |
| 5 | 1 | 6 | -A-C- |
| 6 | 2 | 5 | -C-B- |
| 7 | 2 | 7 | -B-C- |
| 8 | 3 | 8 | -A- |
+----+-----------+----------+--------------+
From this table I would like to select all the rows with "feature" LIKE "%-A-%", but displaying first the result with lowest "position", then all the rows that have same value for column "id_parent" of the first result, then row with the 2nd lowest "position" and all the rows that have same "id_parent" of the result with the 2nd lowest "position", and so on...
So the final result should be:
+----+-----------+----------+--------------+
| id | id_parent | position | feature |
+----+------------+---------+--------------+
| 4 | 3 | 1 | -A-B- |
| 8 | 3 | 8 | -A- |
| 1 | 1 | 2 | -B-A-C- |
| 5 | 1 | 6 | -A-C- |
+----+-----------+----------+--------------+
For some reason I can't explain here I need to have and HAVING clause for selecting the right "feature" value (...HAVING 'feature' LIKE '%-A-%' ...).
Is it possible to make all this with MySQL (possibly without subqueries) or by processing data results with PHP?
Does this help? I've left the last part of the problem as an exercise for the reader...
SELECT a.*
, c.*
FROM my_table a
JOIN
( SELECT id_parent, MIN(position) position FROM my_table WHERE feature = 'a' GROUP BY id_parent ) b
ON b.id_parent = a.id_parent
AND b.position = a.position
JOIN my_table c
ON c.feature = a.feature
AND c.id_parent = a.id_parent;

How can I fetch the values in MySQL?

I have following table name is sk_event:
|------------------------------------------------------------|
| S.No | ticket_id | event_name | sell_amount | coupon_code |
|------------------------------------------------------------|
| 1 | 5 | Airtel | 450 | ABC |
| 2 | 5 | Airtel | 500 | No Code |
| 3 | 6 | Airtel | 250 | XYZ |
| 4 | 5 | Airtel | 450 | ABC |
| 5 | 6 | Airtel | 250 | XYZ |
| 6 | 5 | Airtel | 450 | ABC |
|------------------------------------------------------------|
Second table i have which name is sk_ticket
|------------------------------------|
| S.No. | Ticket_name | ticket Price |
| 5 | 10 KM | 500 |
| 6 | 5 KM | 300 |
|------------------------------------|
I am using following SQL query :
mysqli_query($con, "SELECT * FROM sk_event e INNER JOIN sk_ticket t ON e.ticket_name = t.ticket_name GROUP BY t.ticket_name") or die(mysqli_error($con));
This query is not giving me the result which I want. I want following answer which will be show in datatable bootstraps. I know how to use datatable bootstraps. I just want child row data.
|-------------------------------------------------------------------|
| # | Ticket Name | base Price | Sell Price | Coupon Used | Total |
|-------------------------------------------------------------------|
| + | 10 KM | 500 | - | - | 4 |
| | 10 Km | - | 450 | ABC | 3 |
| | 10 Km | - | 500 | No Code | 1 |
|-------------------------------------------------------------------|
| + | 5 Km | 300 | - | - | 2 |
| | 5 Km | - | 250 | XYZ | 2 |
|-------------------------------------------------------------------|
So, in the above there are two rows result which is indicate by + and every row have some child rows which bifurcate coupon wise data.
How can I show my data like the above table?
Your tried query will not works because you have tried wrong join query, you should do inner join with primary key and foreign key instead of your tried way. Because joins can perform only with primary key and foreign keys.
You can try below query. Hope below query will work for you and you can get your required data.
select * from sk_event se inner join sk_ticket st on se.ticket_id = st.S.No.

Find the ranking for Concatenated rows in mysql

I have a table with concatenated values within both rows, I am therefore uniquely retrieve ranking for each row in the tables.
UPDATE
The other tables has been added to question
NamesTable
NID | Name |
1 | Mu |
2 | Ni |
3 | ices |
GroupTable
GID | GName |
1 | GroupA |
2 | GroupB |
3 | GroupC |
MainTable
| NID | Ages | Group |
| 1 | 84 | 1 |
| 2 | 64 | 1 |
| 3 | 78 | 1 |
| 1 | 63 | 2 |
| 2 | 25 | 2 |
| 3 | 87 | 2 |
| 1 | 43 | 3 |
| 2 | 62 | 3 |
| 3 | 37 | 3 |
Now the first Name is equated to the first age in the table, I am able to equate them using php and foreach statements, Now the problem is with the ranking of the ages per each group. I am ranking the names uniquely on each row or group.
Results which is expected
| Names | Ages | Group | Ranking |
| Mu,Ni,ices | 84,64,78 | 1 | 1,3,2 |
| Mu,Ni,ices | 63,25,87 | 2 | 2,3,1 |
| Mu,Ni,ices | 43,62,37 | 3 | 2,1,3 |
In my quest to solving this, I am using GROUP_CONCAT, and I have been able to come to this level in the below query
SELECT
GROUP_CONCAT(Names) NAMES,
GROUP_CONCAT(Ages) AGES,
GROUP_CONCAT(Group) GROUPS,
GROUP_CONCAT( FIND_IN_SET(Ages, (
SELECT
GROUP_CONCAT( Age ORDER BY Age DESC)
FROM (
SELECT
GROUP_CONCAT(Ages ORDER BY Ages DESC ) Age
FROM
`MainTable` s
GROUP by `Group`
) s
)
)) rank
FROM
`MainTable` c
GROUP by `Group`
This actually gives me the below results.
| Names | Ages | Group | Ranking |
| 1,2,3 | 84,64,78 | 1 | 7,9,8 |
| 1,2,3 | 63,25,87 | 2 | 5,6,4 |
| 1,2,3 | 43,62,37 | 3 | 2,1,3 |
The only problem is that the ranking Values increase from 1 to 9 instead of ranking each row uniquely. Its there any idea that can help me cross over and fix this? I would be grateful for your help. Thanks

Reorder rows within groups

I am making a management system for a site that has a bunch of image galleries. The interface will allow the user to add, delete, or reorder images within each gallery.
I have a table for all the images across all galleries together, with 'id' auto-incremented, and default for sort_order set to 0.
+----+-----------+------------+------------+
| id |gallery_id | sort_order |
+----+-----------+------------+------------+
| 1 | 1 | 1 |
| 2 | 1 | 0 |
| 3 | 1 | 2 |
| 4 | 1 | 3 |
| 5 | 1 | 4 |
| 6 | 1 | 5 |
| 7 | 1 | 6 |
| 8 | 2 | 0 |
| 9 | 2 | 1 |
| 10 | 2 | 2 |
| 11 | 2 | 3 |
| 12 | 2 | 4 |
| 13 | 2 | 5 |
| 14 | 2 | 6 |
+----+-----------+------------+------------+
Here is the reorder query, using a serialized array via ajax:
if($_POST['item']) {
$order = 0;
foreach ($_POST['item'] as $id) {
$rearrange = $db->query
("UPDATE images SET sort_order = '".$order."' WHERE id = '".$id."'");
$order++;
It limits sort_order according to the length of the array that is passed, and then defaults to 0 for the next group its comes to. I can reorder, add, delete, and it always restricts changes to the gallery_id group I am editing.
(As an experiment, I inserted sort_order values ascending across all galleries, like this:
+----+-----------+------------+------------+
| id |gallery_id | sort_order |
+----+-----------+------------+------------+
| 1 | 1 | 0 |
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 1 | 4 |
| 5 | 1 | 5 |
| 6 | 1 | 6 |
| 7 | 1 | 7 |
| 8 | 2 | 8 |
| 9 | 2 | 9 |
| 10 | 2 | 10 |
| 11 | 2 | 11 |
| 12 | 2 | 12 |
| 13 | 2 | 13 |
| 14 | 2 | 14 |
+----+-----------+------------+------------+
And when I reordered rows using my interface, it limited the sort_order within gallery_id groups, exactly as shown in the first table).
I'm looking for caveats to this approach. Anyone done it this way?
UPDATE images
SET
sort_order = FIELD(id, A, B, C, D, E)
WHERE gallery_id = N
AND id IN(A, B, C, D, E)
I do it the same way, but I actually put the image inserted last by calculating the number of rows in each gallery. When a user wants to order he has to filter the list for a specific gallery first then he can sort the images in the gallery.
I cannot but point out the terrible security issues with your code. I really, really, really hope that you are not actually writing the queries like that as anybody can easily do whatever they want with your database.
http://xkcd.com/327/ comes to mind. If I submit an item like 0'; drop table images; your entire table is gone.

Categories