sql new column by delimiter with order ID - mysql

Hi this maybe a simple one but I need help specifically for MYsql
I have the data in one column lets call the column WORK 1,2,3,5,2 (these values are sometimes longer and shorter or more values are present e.g 12,15,11,15,16,143)
I need these to be put into 1 new column for each delimiter and have an ID for the order presented. e.g output

SELECT
*
FROM (SELECT
ROW_NUMBER()
OVER (ORDER BY WORK) AS Row,
RIGHT(LEFT(T.WORK, Number - 1),
CHARINDEX(',', REVERSE(LEFT(',' + T.WORK, Number - 1)))) AS a
FROM master..spt_values,
<YOUR_TABLENAME> T
WHERE Type = 'P'
AND Number BETWEEN 1 AND LEN(T.WORK) + 1
AND (SUBSTRING(T.WORK, Number, 1) = ','
OR SUBSTRING(T.WORK, Number, 1) = '')) AS A

Related

Creating new data table on existing one

Hello I've got a question, how (if it possible), I can create new datatables with close same rows but if In column value is in string "/" for example
ID
column_param
column_sym
column_value
column_val2
First
param_test1
ABC
11/12
test
Second
param_test2
CDE
22/11
test
Third
param_test3
EFG
44
teste
4'th
param_test4
HIJ
33/22
test
And here if I have param_test1 and param_test4 and if in this column value has "/" I want to create 2 other rows but if I will not set param_test2 then it stay as it is and everything should be in new datatable. Is any way to create this?
Thank you in advance.
Expected result:
As per Gordon's answer, I'm not sure what should be done with the your ID column.
I've replaced these with row numbers.
Depending on your version of MySQL/MariaDB, the ROW_NUMBER() window function may not be available. Depending on whether IDs in the output are necessary you may be able to simply omit this.
I've assumed the existence of a table called myNumbers which contains a single field num and is populated with positive integers from 1 to whatever you're likely to need.
I've included more in the output that you asked for, which will hopefully help you understand what's going on
SELECT
ROW_NUMBER() OVER (ORDER BY d.ID, n.num) as NewID,
d.ID as OriginalID,
n.num as,
d.column_param,
d.column_sym,
d.column_value as orig_value,
CASE WHEN column_param = 'param_test2' THEN d.column_value
ELSE substring_index(substring_index(d.column_value,'/',n.num),'/',-1) END as split_value,
d.column_val2
FROM
myData d
JOIN myNumbers n on char_length(d.column_value)-char_length(replace(d.column_value,'/','')) >= n.num-1
WHERE
n.num = 1 OR d.column_param <> 'param_test2'
ORDER BY
d.ID,
n.num
See this DB Fiddle (the columns output in a different order than I've specified, but I think that's a DB Fiddle quirk).
If you only want to "split" say param_test1 and param_test4 rows the code above code could be amended as follows:
SELECT
ROW_NUMBER() OVER (ORDER BY d.ID, n.num) as NewID,
d.ID as OriginalID,
d.column_param,
d.column_sym,
n.num,
d.column_value as orig_value,
CASE WHEN column_param NOT IN ('param_test1','param_test4') THEN d.column_value
ELSE substring_index(substring_index(d.column_value,'/',n.num),'/',-1) END as split_value,
d.column_val2
FROM
myData d
JOIN myNumbers n on char_length(d.column_value)-char_length(replace(d.column_value,'/','')) >= n.num-1
WHERE
n.num = 1 OR d.column_param IN ('param_test1','param_test4')
ORDER BY
d.ID,
n.num
I don't know how the id is being set, but you can do what you want using union all:
select column_param, column_sym,
substring_index(column_value, '/', 1) as column_value,
column_val2
from t
union all
select column_param, column_sym,
substring_index(column_value, '/', -1) as column_value,
column_val2
from t
where column_value = '%/%';

Math operations on products alpha-num serial numbers | Database Design

So in my database, I got the tables
Product (prodId,Name,Price)
Box (BoxId,prodId,From,To,Available)
'From' represents the first serial number. And 'To' the ending serial.
Calculating 'To' sub 'From' gives the quantity of products.
A client comes and makes an order of a given product with a given quantity. What I need ,is given the 'From' serial number,I calculate 'From' + Quantity.
If the serial numbers were only sequential integers. This would be easy. But this applies to all types of products with different serial numbers.
For ex :
Box( 1,1,ABC00000C,ABC00099K,100)
What I want to achieve is this :
SELECT From + 50 FROM BOX
How Can i deal with the serial number to get the order ending serial ?
To deal with such serial numbers you need either (option 1) a fn(x) calculating a serial number given an integer x, or (option 2) a list of available serial numbers.
Option 1 is easiest to implement, but it requires that the person thinking up the serial number format actually did think of making up a conversion formula to convert an integer into a serial number also. If such a formula exists, all you need to do is determine the integer value for the "from"-value, add 50 to this integer value 'x' and determine the serial number for 'x + 50'.
Option 2 requires that you have a list, or can generate a list of serial numbers, plus those serial numbers must be (somehow) logically ordered. Option 2 then applies one of many ways SQL server provides to get the next 50 rows from this list, starting from the row with value "From" in it. Examples of such methodes are "select top (50) ...", window function "row_number() over (order by ...)", "select ... order by ... offset n rows fetch next 50 rows only" or even a cursor.
Added after comment from Wildfire:
I suggest you create a table holding the serials for option 2. Let me explain this by giving an example: what would you do if one item with serial n + 5 happens to have fallen of the production line and was damaged beyond repair? I.e. this one serial number will never be shipped to a customer. I bet you are not going to ship a box with one less item when this happens, nor are you going to discard 49 undamaged products because the one item is missing. Instead you will probably put all products with serials n to n + 4 and n + 6 to n + 51 in a box, leaving serial n + 5 out. In a perfect world this will of course never happen, but in real life things do go wrong sometimes, so you need to able to cope with -for example- missing serials. So I would really suggest creating a table with all serials available for boxing, and simply have your boxing process read it's next 50 serials from this table.
And option 1 can work, even if the serial itself is non-numerical but can be calculated into a numerical. It's just a little more complicated. That's why I said a formula must exist for the serials for the method to work. Here's an example how you could add 50 to serial "ABC00000C", making "ABC00001Y" the to serial:
declare #from varchar(9) = 'ABC00000C';
declare #from_int bigint;
with cteSerialCharacters as (
-- The set of characters used in a serial.
-- As an example I've taken all number characters plus
-- all capital letters from the alphabet excluding any
-- of these that are easily misread.
select '0123456789ABCDEFGHJKLMNPRSTVWXYZ' as chars
),
cteNumberGenerator as (
select cast (row_number() over (order by (select null)) as bigint) as n
from ( select 1 union all select 1 union all select 1 union all select 1
union all select 1 union all select 1 union all select 1
union all select 1 union all select 1
) t (xyz)
)
select
#from_int = sum(power(s.base, (n - 1)) * (-1 + charindex(substring(reverse(s.serial), n.n, 1), s.characterset)))
from (
select
#from,
cast(len(ch.chars) as bigint),
ch.chars
from cteSerialCharacters ch
) s (serial, base, characterset)
inner join cteNumberGenerator n on (n.n <= len(s.serial));
select #from, #from_int;
declare #to varchar(9);
declare #to_int bigint;
select #to_int = #from_int + 50;
with cteSerialCharacters as (
-- The set of characters used in a serial.
-- As an example I've taken all number characters plus
-- all capital letters from the alphabet excluding any
-- of these that are easily misread.
select '0123456789ABCDEFGHJKLMNPRSTVWXYZ' as chars
),
cteNumberGenerator as (
select cast (row_number() over (order by (select null)) as bigint) as n
from ( select 1 union all select 1 union all select 1 union all select 1
union all select 1 union all select 1 union all select 1
union all select 1 union all select 1
) t (xyz)
)
select
#to = (
select
substring(s.characterset, 1 + (#to_int / power(s.base, n.n - 1)) % s.base, 1) as [text()]
from (
select
cast(len(ch.chars) as bigint),
ch.chars
from cteSerialCharacters ch
) s (base, characterset)
cross join cteNumberGenerator n
order by n.n desc
for xml path(''), type
).value('text()[1]', 'varchar(9)')
select #to, #to_int;

getting maximum value of a varchar column in database

how can i get the maximum value of my column that is a varchar with these values
for example i have a fieldname of myid which is varchar and what i want is to get the maximum value of the myid field . How can i query to get the 1-10 value of myid column?
myid
1-1
1-2
1-3
1-4
1-5
1-6
1-7
1-8
1-10
1-9
I would suggest using this trick:
order by length(myid) desc, myid desc
This will work for the data in the question. A more general answer is:
order by substring_index(myid, '-', 1) + 0, substring_index(myid, '-', -1) + 0
For the data you've shown:
select myid
from data_table
order by cast(substr(myid, 3, 2) as int) desc
limit 1;
In this case the ordering function is the integer value of the portion of the identifier following the dash. In general--i.e., for different or more complex data--you simply need to determine what the appropriate odering function is.

Counting comma separated values in TSQL

SCHEMA / DATA for TABLE :
SubscriberId NewsletterIdCsv
------------ ---------------
11 52,52,,52
We have this denormalized data, where I need to count the number of comma separated values, for which I am doing this :
SELECT SUM(len(newsletteridcsv) - len(replace(rtrim(ltrim(newsletteridcsv)), ',','')) +1) as SubscribersSubscribedtoNewsletterCount
FROM TABLE
WHERE subscriberid = 11
Result :
SubscribersSubscribedtoNewsletterCount
--------------------------------------
4
The problem is some of our data has blanks / spaces in between the comma separated values, if I run the above query the expected result should be 3 (as one of the value is blank space), how do I check in my query to exclude the blank spaces?
EDIT :
DATA :
SubscriberId NewsletterIdCsv
------------ ---------------
11 52,52,,52
12 22,23
I need to get an accumulative SUM instead of just each rows sum, so for this above data I need to have just a final count i.e. 5 in this case, excluding the blank space.
Here's one solution, although their may be a more efficient way:
SELECT A.[SubscriberId],
SUM(CASE WHEN Split.a.value('.', 'VARCHAR(100)') = '' THEN 0 ELSE 1 END) cnt
FROM
(
SELECT [SubscriberId],
CAST ('<M>' + REPLACE(NewsletterIdCsv, ',', '</M><M>') + '</M>' AS XML) AS String
FROM YourTable
) AS A
CROSS APPLY String.nodes ('/M') AS Split(a)
GROUP BY A.[SubscriberId]
And the SQL Fiddle.
Basically it converts your NewsletterIdCsv field to XML and then uses CROSS APPLY to split the data. Finally, using CASE to see if it's blank and SUM the non-blank values. Alternatively, you could probably build a UDF to do something similar.

How to order by two values in MySQL?

I want a query that would order them by this kind of results :
column = 1
column = 2
column = 1
column = 2
and repeat
you see what i mean is, i want it to list results of two values of the same column value by value
EDIT :
ill make it more simple, column name has two values to verify something of 1 and 0
i want to use php to sort them down eachother but 1 follows it 0 and again 1 follows it 0, keeps going on this
table has other info that i want to extract but sorted by how its written aboce ^
Here's my overly complicated code.
select bar
from (select bar, (#t := #t + 2) t
from foo, (select #t := 0) dummy
where bar = 1
union all
select bar, (#t2 := #t2 + 2) t
from foo, (select #t2 := 1) dummy
where bar = 2) temp
order by t;
Live demo: http://sqlfiddle.com/#!2/5d5f0/19
Try below code:
$sqlQuery1 = "SELECT distinct grade FROM loglists where
speciesNo='".$speciesData['speciesNo']."' and voyageNo='".$_REQUEST[voyageNo]."' order by
grade ASC, combinedgrade DESC";
I think this is the best solution for arrange order by multiple value.
select * from hotel where confId=13 group by hotelName ORDER BY CASE WHEN rating = '5 Star'
THEN 1
WHEN rating = '4 Star'
THEN 2
WHEN rating = '3 Star'
THEN 3
WHEN rating = 'BUDGET & EQUIVALENT HOTELS'
THEN 4
END
"select * from table order by field2,field3,field4";
the above sytnax is to order by multiple fields
use a foreach statement and check if its column1 and column 2 and display them