MySQL ORDER By one Specific value in column (having comma separated values) - mysql

I want to sort the user record according to city (chosen from the drop-down list). like if I pass city_id 22 in my query then i want all the row first which are having city_ids 22 then the rest of the rows.
I know WHERE find_in_set('22',city_ids) will give me the correct result but it will not return the all rows so I want to achieve it using some ORDER BY .
I have tried ORDER BY FIND_IN_SET('22',city_ids) but its not working. How do I fix this, any best way?
User Table:
Id Name city_ids
1 AAAAA 10,22,30
2 BBBBB 11,28
3 CCCCC 15,22,44
4 DDDDD 19,99,
5 EEEEE 55,27,22
Want Sorted Output like below:
Id Name city_ids
1 AAAAA 10,22,30
3 CCCCC 15,22,44
5 EEEEE 55,27,22
2 BBBBB 11,28
4 DDDDD 19,99,

You can do:
ORDER BY (FIND_IN_SET('22', city_ids) > 0) DESC
This puts matches first.
Then you should fix your data model. It is broken, broken, broken. Storing lists of ids in a string is wrong for many reasons:
The data types are (presumably) wrong. The ids are numbers and should not be stored as strings.
Storing multiple values in a column is not the SQL way to store things.
Ids should have properly declared foreign key relationships, which you cannot declare.
SQL does not have very good functions for processing strings.
The resulting queries cannot take advantage of indexes or partitioning, impeding performance.
SQL has this really great data structure for storing lists of things. It is called a table, not a string column.

The expression:
FIND_IN_SET('22', city_ids) > 0
will return 1 for all rows where '22' exists in column city_ids and 0 for the others.
So, after that you need add one more level for sorting by id ascending:
ORDER BY
FIND_IN_SET('22', city_ids) > 0 DESC,
id
See the demo.
Results:
| Id | Name | city_ids |
| --- | ----- | -------- |
| 1 | AAAAA | 10,22,30 |
| 3 | CCCCC | 15,22,44 |
| 5 | EEEEE | 55,27,22 |
| 2 | BBBBB | 11,28 |
| 4 | DDDDD | 19,99 |

Related

Laravel get "unique" row from mysql

I have a special scenario to fetch "unique" row.
Let's say the database is like below
| id | userid | value | others |
|----|--------|-------|---------|
| 1 | 111 | 10 | string1 |
| 2 | 112 | 30 | string2 |
| 3 | 112 | 30 | string3 |
| 4 | 113 | 50 | string4 |
what I want to achieve is to fetch the unique rows based on the "userid" so I'am able to sum all values.
the expect output row can be either id: 1 2 4 or 1 3 4 (both is acceptable for this special case because same id guarantees same value, or in general, get just one row from those row with same userid. ), so the sum will be 90.
Note: DB is extended from Eloquent\model
My old approach is to get DB::unique('userid'); then for each userid DB::where('userid', $id)->value('value'), add the result to sum; I just believe there might be a better approach.
There is Illuminate\Support\Facades\DB in Laravel, it can return the Query Builder. Not recommend to use a model that is named DB.
So just change another name.
By the way, for Eloquent\Model, you can use groupBy and sum too:
Model::groupBy('user_id')->sum('value');

Skipping row for each unique column value

I have a table from which I would like to extract all of the column values for all rows. However, the query needs to be able to skip the first entry for each unique value of id_customer. It can be assumed that there will always be at least two rows containing the same id_customer.
I've compiled some sample data which can be found here: http://sqlfiddle.com/#!9/c85b73/1
The results I would like to achieve are something like this:
id_customer | id_cart | date
----------- | ------- | -------------------
1 | 102 | 2017-11-12 12:41:16
2 | 104 | 2015-09-04 17:23:54
2 | 105 | 2014-06-05 02:43:42
3 | 107 | 2011-12-01 11:32:21
Please let me know if any more information/better explanation is required, I expect it's quiet a niche solution.
One method is:
select c.*
from carts c
where c.date > (select min(c2.date) from carts c2 where c2.id_customer = c.id_customer);
If your data is large, you want an index on carts(id_customer, date).

Need help on SQL query - Select data with duplicate multiple data entries in one data field

I need to select all data having non-duplicate IDs..
here's my sample table..
----------------------------------------------------------------------------------
ID | Zip-Code | Search Query | ID_LIST
----------------------------------------------------------------------------------
1 | 1000 | Query Sample 1 | 13,14,15,
----------------------------------------------------------------------------------
2 | 2000 | Query Sample 2 | 16,13,17,
----------------------------------------------------------------------------------
3 | 3000 | Query Sample 3 | 18,17,13,
----------------------------------------------------------------------------------
4 | 4000 | Query Sample 4 | 15,16,17,18,
----------------------------------------------------------------------------------
5 | 5000 | Query Sample 5 | 19, 20,
u can notice that IDs 1 and 2 have duplicate, which is 13 on ID_LIST
2 and 3 also have duplicate, which is 13 and 17.
What I want to do is make it like this...
----------------------------------------------------------------------------------
ID | Zip-Code | Search Query | ID_LIST
----------------------------------------------------------------------------------
1 | 1000 | Query Sample 1 | 13,14,15,
----------------------------------------------------------------------------------
2 | 2000 | Query Sample 2 | 16,17,
----------------------------------------------------------------------------------
3 | 3000 | Query Sample 3 | 18,
----------------------------------------------------------------------------------
5 | 5000 | Query Sample 5 | 19,20,
What query would be good for this? Any Help?
Best way to approach it is to normalize your data, as mentioned in comments. But if you absolutely have to do it this way, it would be very difficult to do in query on mysql.
I would suggest you to create a procedure for it. As and when you develop each step, you can google that particular solution of that step, and test it and build up on that. Let me know if any step sound confusing/unclear.
Create a variable string, say v_vals. Initialize with null. At the end of procedure, it will contain all the distinct values of id_list (13,14...20)
Iterate through each row.
Count the number of comma in id_list.
Loop from 1 to number of comma.
In every iteration, use substring and instring to find position of each comma and then extract values from id_list. (13,14...)
use another variable v_id_list. Put null in it.
Search for the values (from step 5) in v_vals. If they exist in v_val, then skip them, else put them in v_val and v_id_list.
Now run an update statement to update id_list with v_id_list.
Now repeat Step 3 to 8 for each row.
Note that v_id_list will be reinitialize for each loop, however v_val will contain all the distinct values of id_list.

MySQL Table Structure - Storing a limited set of numbers

I need to store a set of numbers in a MySQL database. I need some help to determine the best table structure to use.
There are 20 numbers that will be stored in each row, along with an ID. The numbers can range from 1 - 80 and there are no repeats in this series of numbers.
Initially I created a table structure with 21 columns, an ID and 20 columns that store each individual number.
Id | Num1 | Num2 | Num3 | Num4 | Num5 | etc.. |
----------------------------------------------------------
0001 | 1 | 4 | 15 | 22 | 39 | 43 |
0002 | 3 | 5 | 22 | 43 | 55 | 58 |
0003 | 1 | 3 | 5 | 6 | 15 | 26 |
I've also thought of a table with 81 columns, an ID and 80 boolean columns that would represent each individual number.
Id | 1 | 2 | 3 | 4 | 5 | etc.. |
----------------------------------------------------------
0001 | True | False | False | True | True | False |
0002 | False | False | True | False | True | False |
0003 | True | False | True | False | True | True |
Can anyone give some advice to the pros and cons of each table structure, and which would be easier to use when searching this table.
For example, we would need to search for every row that contains 1,2,5,66, and 79.
Or every row that contains 16,33, and 4.
Any guidence would be appreciated.
What you're looking for is called database normalization; a way to organize data that prevents duplication and anomalies (like changing one record inadvertently changing another record).
Higher-normal forms depend on the meaning of your data, which you have not told us, but to start you should avoid ordered or indeterminate columns (like Num1, Num2, ...) and split your columns into rows:
ID Num
0001 1
0001 4
0001 15
...
0002 3
0002 5
...
In general, any time you find yourself adding a bunch of columns that depend on their position you are making a mistake. SQL has many functions for aggregating, combining, sorting, and reporting on rows. Use the features of SQL to produce the results you want; don't try to make your database schema look like the final printed report.
In answer to your comment, a query that returns only IDs that have Nums 1, 4, and 15, and no other ID:
select ID from YourTable
where Num in (1, 4, 15)
group by ID
having Count(ID) = 3
If Nums can be duplicated you will want something like having count(distinct ID). If you can have different counts of Nums to match you will have to create a temporary table of Nums to match and use having count(ID) = (select Count(Num) from TemporaryTable).
Note that SQL Server already has a master..spt_values table of integers to use in such situations; I do not know if MySql has such a thing, but they are easy to generate if you need one.

MySQL data in column wise which is stored in row based

I am having a table with data stored in row basis as shown below.
UID | DetailsID | Data|
----------------------|
1 | 1 | A |
1 | 2 | 200|
1 | 3 | 2010-10-11 08:32 |
2 | 1 | B |
2 | 2 | 600|
2 | 3 | 2011-05-20 14:56 |
From this I need the output as follows
UID|1|2|3
------------
1|A|200|2010-10-11 08:32
2|B|600|2011-05-20 14:56
Here main thing is, the number of entries of DetailsID values is not known.
I wanted this one in MySQL.
Please help me out of this.
Not quite what you want, but other than loads of left joins i can only suggest:
SELECT UID,GROUP_CONCAT(DetailsID SEPARATOR ",") "DetailsIDs",GROUP_CONCAT(Data SEPARATOR ",") "Data" FROM data_table GROUP BY UID;
Do that transformation in your coding language, not in SQL.
you didnt say where you need the output. If you need the output in PHP pages it is simple only by creating the loop for the entries in columns wise.