mysql does not sort properly - mysql

I have the following table with entries
+--------------------------------------------+----------+
| menu_entry | position |
+--------------------------------------------+----------+
| ADMINISTRATION::USERMANAGEMENT::USER | 2 |
| DEMO::CHART::EXAMPLE | 1 |
| PROJMGMT::PROJSTRG::LOP | 2 |
| ADMINISTRATION::USERMANAGEMENT::RIGHTSMMGT | 1 |
| PROJMGMT::PROJSTRG::MEETINGS | 1 |
| DEMO::GRID::CELLEDIT | 1 |
| DEMO::GRID::ROWEDIT | 3 |
| DEMO::DATAMGMT::GROUPING | 1 |
| DEVELOPER::APPS::ADDAPP | 2 |
| DEVELOPER::APPS::APPTEST | 1 |
| DEMO::GRID::LOCKINGDEMO | 4 |
| DEMO::GRID::FILTERDEMO | 2 |
+--------------------------------------------+----------+
I want to order by menu_entry first and second by position. I do that with the following Statement
select menu_entry,position from app_names order by menu_entry, position;
But it only sorts by menu_entry and not by Position.
Here's the return of my statement:
+--------------------------------------------+----------+
| menu_entry | position |
+--------------------------------------------+----------+
| ADMINISTRATION::USERMANAGEMENT::RIGHTSMMGT | 1 |
| ADMINISTRATION::USERMANAGEMENT::USER | 2 |
| DEMO::CHART::EXAMPLE | 1 |
| DEMO::DATAMGMT::GROUPING | 1 |
| DEMO::GRID::CELLEDIT | 1 |
| DEMO::GRID::FILTERDEMO | 2 |
| DEMO::GRID::LOCKINGDEMO | 4 |
| DEMO::GRID::ROWEDIT | 3 |
| DEVELOPER::APPS::ADDAPP | 2 |
| DEVELOPER::APPS::APPTEST | 1 |
| PROJMGMT::PROJSTRG::LOP | 2 |
| PROJMGMT::PROJSTRG::MEETINGS | 1 |
+--------------------------------------------+----------+
As you can see, DEMO::GRID::... is not sorted right.

You should probably order by SUBSTRING_INDEX(menu_entry, '::', 1) that extracts the part of the string at the left of the first :: or by SUBSTRING_INDEX(menu_entry, '::', 2), depending on what you are after:
select menu_entry, position
from app_names
order by
SUBSTRING_INDEX(menu_entry, '::', 1), position;
Please see fiddle here.

Related

how to sort sql data for given table?

+---------+----------------+--------+
| aid | fn | col_no |
+---------+----------------+--------+
| 2011768 | ABDUL | 5 |
| 2011499 | ABDULLA | 4 |
| 2011198 | ADNAN | 3 |
| 2011590 | AKSHAYA PRAISY | 2 |
| 2011749 | AMIR | 1 |
| 2011213 | AMOGHA | 5 |
| 2011027 | ANU | 4 |
| 2011046 | ANUDEV D | 3 |
| 2011435 | B S SAHANA | 2 |
| 2011112 | BENAKA | 1 |
+---------+----------------+--------+
How to sort the number like col_no as 1 2 3 4 5 and again repeat as 1 2 3 4 5?
i need output like this
+---------+----------------+--------+
| aid | fn | col_no |
+---------+----------------+--------+
| 2011749 | AMIR | 1 |
| 2011590 | AKSHAYA PRAISY | 2 |
| 2011198 | ADNAN | 3 |
| 2011499 | ABDULLA | 4 |
| 2011768 | ABDUL | 5 |
| 2011112 | BENAKA | 1 |
| 2011435 | B S SAHANA | 2 |
| 2011046 | ANUDEV D | 3 |
| 2011027 | ANU | 4 |
| 2011213 | AMOGHA | 5 |
+---------+----------------+--------+
You can use row_number() partition by col_no:
select t.*
from t
order by row_number() over (partition by col_no order by fn),
col_no;
Here is a db<>fiddle.

Enumerate rows in mysql based on groups with dates in different columns

I have a question very similar to this one, but different (aka, I couldn't extend the answer to that one to fit my purposes. Due to the second WHERE condition, specifically).
I have a table which tracks the visit number for customers. There are two types of visits:
| ID | InStoreVisit | InStoreDate | OnlineVisit | OnlineDate |
|----|--------------|-------------|-------------|------------|
| 1 | 1 | 1/1/11 | | |
| 1 | 2 | 1/2/11 | | |
| 1 | | | 1 | 1/3/11 |
| 1 | 3 | 1/4/11 | | |
| 2 | | | 1 | 2/2/12 |
| 2 | 1 | 2/3/12 | | |
| 2 | | | 2 | 2/4/12 |
I need to create a new column which has a sort of 'global visit number' as such:
| ID | InStoreVisit | InStoreDate | OnlineVisit | OnlineDate | GobalVisit |
|----|--------------|-------------|-------------|------------|------------|
| 1 | 1 | 1/1/11 | | | 1 |
| 1 | 2 | 1/2/11 | | | 2 |
| 1 | | | 1 | 1/3/11 | 3 |
| 1 | 3 | 1/4/11 | | | 4 |
| 2 | | | 1 | 2/2/12 | 1 |
| 2 | 1 | 2/3/12 | | | 2 |
| 2 | | | 2 | 2/4/12 | 3 |
I'm getting mixed up on the WHERE condition with which I can do the self-join. Any advice greatly appreciated.

Selected Child Categories based on parent categories from another table

I have two tables
rules
With three step hierarchy
|id | name | parent |
|---|-------|--------|
| 1 | A | 0 |
| 2 | B | 0 |
| 3 | A(1) | 1 |
| 4 | A(2) | 1 |
| 5 | B(1) | 2 |
| 6 | A(1.1)| 3 |
| 7 | A(1.2)| 3 |
| 8 | A(2.1)| 4 |
| 9 | B(1.1)| 5 |
| 10| A(3) | 1 |
Subject
|id | date | rules | group |
|---|---------------------|-------|-------|
| 1 | 2016-05-20 18:24:20 | 2 | AQR48 |
| 2 | 2016-05-20 19:31:17 | 5 | AQR52 |
| 3 | 2016-05-21 18:11:37 | 6,7,4 | AQR48 |
I need to get second step rules based on group and ruleid(first step) of subject table data
When group = 'AQR48' and rules.parent=1 result should be
|id | name | parent |
|---|-------|--------|
| 3 | A(1) | 1 |
| 4 | A(2) | 1 |
I tried it like this but with out success.
select rules.id,rules.name,rules.parent from rules left join subject on find_in_set(rules.id,subject.rules) where rules.parent=1 AND subject.group='AQR48'
With this I get output as
|id | name | parent |
|---|-------|--------|
| 4 | A(2) | 1 |
Anyone could help me with this

How to join 3 tables in order to get a result with two tables alternating

Say I have 3 tables, foo bar and baz, where bar and baz having different additional informations about the datasets in foo. Is there a way to join these 3 tables together, so that in every output row is either a (foo <join> bar) or (foo <join> baz) dataset?
Say, I have the following tables:
mysql> select * from foo;
+----+-------+
| id | foo |
+----+-------+
| 1 | start |
| 2 | mid |
| 3 | end |
+----+-------+
mysql> select * from bar;
+----+-----+-----------+
| id | bid | bar |
+----+-----+-----------+
| 1 | 1 | bar-start |
| 2 | 2 | bar-mid |
| 3 | 3 | bar-end |
+----+-----+-----------+
mysql> select * from baz;
+----+-----+-------------+
| id | bid | baz |
+----+-----+-------------+
| 1 | 1 | baz-start-1 |
| 1 | 2 | baz-start-2 |
| 1 | 3 | baz-start-3 |
| 2 | 4 | baz-mid-1 |
| 2 | 5 | baz-mid-2 |
| 2 | 6 | baz-mid-3 |
| 3 | 7 | baz-end-1 |
| 3 | 8 | baz-end-2 |
| 3 | 9 | baz-end-3 |
+----+-----+-------------+
I can extract all the information with a query which joins those tables together via
mysql> select * from foo join bar join baz on foo.id = bar.id and foo.id=baz.id;
+----+-------+----+-----+-----------+----+-----+-------------+
| id | foo | id | bid | bar | id | bid | baz |
+----+-------+----+-----+-----------+----+-----+-------------+
| 1 | start | 1 | 1 | bar-start | 1 | 1 | baz-start-1 |
| 1 | start | 1 | 1 | bar-start | 1 | 2 | baz-start-2 |
| 1 | start | 1 | 1 | bar-start | 1 | 3 | baz-start-3 |
| 2 | mid | 2 | 2 | bar-mid | 2 | 4 | baz-mid-1 |
| 2 | mid | 2 | 2 | bar-mid | 2 | 5 | baz-mid-2 |
| 2 | mid | 2 | 2 | bar-mid | 2 | 6 | baz-mid-3 |
| 3 | end | 3 | 3 | bar-end | 3 | 7 | baz-end-1 |
| 3 | end | 3 | 3 | bar-end | 3 | 8 | baz-end-2 |
| 3 | end | 3 | 3 | bar-end | 3 | 9 | baz-end-3 |
+----+-------+----+-----+-----------+----+-----+-------------+
But I would like to get an output like the following table, since that would make the code in the application consuming the data much simpler:
+----+-------+------+------+-----------+------+------+-------------+
| id | foo | id | bid | bar | id | bid | baz |
+----+-------+------+------+-----------+------+------+-------------+
| 1 | start | 1 | 1 | bar-start | NULL | NULL | NULL |
| 1 | start | NULL | NULL | | 1 | 1 | baz-start-1 |
| 1 | start | NULL | NULL | | 1 | 2 | baz-start-2 |
| 1 | start | NULL | NULL | | 1 | 3 | baz-start-3 |
| 2 | mid | 2 | 2 | bar-mid | NULL | NULL | NULL |
| 2 | mid | NULL | NULL | | 2 | 4 | baz-mid-1 |
| 2 | mid | NULL | NULL | | 2 | 5 | baz-mid-2 |
| 2 | mid | NULL | NULL | | 2 | 6 | baz-mid-3 |
| 3 | end | 3 | 3 | bar-end | NULL | NULL | NULL |
| 3 | end | NULL | NULL | | 3 | 7 | baz-end-1 |
| 3 | end | NULL | NULL | | 3 | 8 | baz-end-2 |
| 3 | end | NULL | NULL | | 3 | 9 | baz-end-3 |
+----+-------+------+------+-----------+------+------+-------------+
Is there a way to convince mysql to give me a result set like the last one?
(
select foo.id as foo_id, foo.foo, bar.id, bar.bid, bar.bar, null, null as baz_bid, null as baz from foo
join bar on foo.id=bar.id
)
union
(
select foo.id as foo_id, foo.foo, null, null, '', baz.id, baz.bid as baz_bid, baz.baz from foo
join baz on foo.id=baz.id
)
order by foo_id asc, bar desc, baz_bid asc

Populating a column by extracting a value from other column in the same table

I have a table callInfo and it looks like this:
+----+------------------------------------------------------------------------------------------------------------------------------------+
| id | idUrl | collectionId | |
+----+------------------------------------------------------------------------------------------------------------------------------------+
| 1 | id?books.0.levelOfDetail=high&books.0.shopId=727&books.0.type=books&collectionId=20092014&type=seasonPassSource | |
| 2 | id:call3?books.0.levelOfDetail=high&books.0.shopId=123&books.0.type=books&collectionId=16645&type=seasonPassSource | |
| 3 | id:call3?maxDepth=1&parentMixId=777&type=mixSource | |
| 4 | idSet:call3?keyword=%22FOO%20BAR%20.%5E%24*%2B%3F%7C%28%29%7B%7D%5B%5D%22&type=wishListSource | |
| 5 | idSet:call3?books.0.levelOfDetail=high&books.0.shopId=727 | |
| 6 | idSetSource.0.booksNumber=2&collectionId=16645&books.0.levelOfDetail=high&books.0.type=books&type=seasonPassSource | |
| 7 | idSet:call3?keyword=hero&type=wishListSource | |
+----+-------------------------+----------------------------------------------------------------------------------------------------------+
I have created a new column called collectionId in the table callInfo, but the are many records in the table for which I need to update this column value.
I need to extract the value of collectionId from idUrl column and put it in collectionId column.
it should look like this
+----+------------------------------------------------------------------------------------------------------------------------------------+
| id | idUrl | collectionId | |
+----+------------------------------------------------------------------------------------------------------------------------------------+
| 1 | id?books.0.levelOfDetail=high&books.0.shopId=727&books.0.type=books&collectionId=20092014&type=seasonPassSource | 20092014 |
| 2 | id:call3?books.0.levelOfDetail=high&books.0.shopId=123&books.0.type=books&collectionId=16645&type=seasonPassSource | 16645 |
| 3 | id:call3?maxDepth=1&parentMixId=777&type=mixSource | NULL |
| 4 | idSet:call3?keyword=%22FOO%20BAR%20.%5E%24*%2B%3F%7C%28%29%7B%7D%5B%5D%22&type=wishListSource | NULL |
| 5 | idSet:call3?books.0.levelOfDetail=high&books.0.shopId=727 | NULL |
| 6 | idSetSource.0.booksNumber=2&collectionId=16645&books.0.levelOfDetail=high&books.0.type=books&type=seasonPassSource | 16645 |
| 7 | idSet:call3?keyword=hero&type=wishListSource | NULL |
+----+-------------------------+----------------------------------------------------------------------------------------------------------+
I need to do this in MySQL. Any ideas?
Another way to do it using SUBSTRING_INDEX()
UPDATE callInfo
SET collectionId = SUBSTRING_INDEX(SUBSTR(idUrl, INSTR(idUrl, 'collectionId=') + 13), '&', 1)
WHERE idUrl LIKE '%collectionId=%'
Output:
| ID | ... | COLLECTIONID |
|----| ... |--------------|
| 1 | ... | 20092014 |
| 2 | ... | 16645 |
| 3 | ... | (null) |
| 4 | ... | (null) |
| 5 | ... | (null) |
| 6 | ... | 16645 |
| 7 | ... | (null) |
Here is SQLFiddle demo