This question already has answers here:
Filter rows in a column based on set rules in SQL
(2 answers)
Closed 1 year ago.
Group ID Values Month
1 09239820 43 May
2 2872498938 23 Jan
2 1267 18 Dec
3 23219823983 09 Sept
3 267839236 11 July
4 33287442 23 Jan
I want to replace the 1st, 2nd and 4th numbers in the ID column with letters
Replace 1st with N
Replace 2nd with X
Replace 4TH with D
Expected output:
Group ID Value Month
1 NX2D9820 43 May
2 NX7D498938 23 Jan
2 NX6D 18 Dec
3 NX2D9823983 09 Sept
3 NX7D39236 11 July
4 NX2D7442 23 Jan
I am new to SQL, and I have written the following code below (it is not working)
SELECT * FROM #table# t1;
UPDATE t1 SET ID = CONCAT('NX', SUBSTRING(ID,3,1), 'D', SUBSTRING(ID,5));
SELECT * FROM t1;
I found a way of doing this task, maybe it is not the simplest and fastest one but it make sense. If somebody think of any improvement on the query, feel free to edit my answer.
UPDATE test_01 tbl1
INNER JOIN (
select `group`, concat_ws('',substring(RIGHT((insert(id, 1, 2, 'NX')), 9999),1,3), substring(LEFT((insert(id, 4, 1, 'D')), 9999),4,9999)) as id_tbl2
from test_01)
as tbl2
ON tbl1.`group` = tbl2.`group`
SET tbl1.id = tbl2.id_tbl2;
Working demo:https://www.db-fiddle.com/f/7yUJcuMJPncBBnrExKbzYz/6
Let me explain what the query does
insert(id, 1, 2, 'NX') ---> inserts NX in first and second place
insert(id, 4, 1, 'D' ---> inserts D in the fourth place
substring(RIGHT((insert(id, 1, 2, 'NX')), 9999),1,3) ---> select
first three characters changed
substring(LEFT((insert(id, 4, 1, 'D')), 9999),4,9999) ---> select from the fourth character to the end
of the row because 9999 extends the column limit
Using concat_ws I combine tha changed data to a new table and in the
end we can update using the join condition.
Related
Refer to the image above.
I have Table 1, and I want to produce Table 2 with SQL.
The first year has to be set to the value 10. The values following will multiply 10 by the multiplier for that year and previous years in Table 1.
For example:
For 2002, the value will be 10 * 2 (2002 multiplier) * 1 (2001 multiplier) = 20.
For 2005, the value will be 10 * 5 * 3 * 1 * 2 * 1 (all previous year multipliers) = 300.
How would I go about doing this? I'd appreciate any help.
A colleague of mine long ago taught me a trick to solve this kind of problems using logarithm properties.
Basically you can do:
Exp(sum(ln(multiplier)))
Edited after the OP made me realize it was incomplete
To do the cumulative logic you need you should apply this on a self-join
select a.youryear, Exp(sum(ln(b.multiplier))) cumulative_mutiplier
from yourtable as a
join
yourtable as b on a.youryear>=b.youryear
group by a.youryear;
I've prepared a test on rextester
create table yourtable (
youryear integer,
multiplier integer
);
insert into yourtable(youryear,multiplier) values (2000,10);
insert into yourtable(youryear,multiplier) values (2001,1);
insert into yourtable(youryear,multiplier) values (2002,2);
insert into yourtable(youryear,multiplier) values (2003,1);
insert into yourtable(youryear,multiplier) values (2004,3);
insert into yourtable(youryear,multiplier) values (2005,5);
select a.youryear, Exp(sum(ln(b.multiplier))) cumulative_mutiplier
from yourtable as a
join
yourtable as b on a.youryear>=b.youryear
group by a.youryear;
The result is:
youryear cumulative_mutiplier
1 2000 10
2 2001 10
3 2002 20
4 2003 20
5 2004 60
6 2005 300
select year
,x
,#result := #result*coalesce(x,10) as result
from table1,(select #result:=1) i
order by year
;
# year, x, result
2000, , 10
2001, 1, 10
2002, 2, 20
2003, 1, 20
2004, 3, 60
2005, 5, 300
I'm trying to normalize some data, and can't seem to come up with a solution. What I have is a table like this:
weight position1 position2 position3
1 10 20 30
2 25 35 45
3 17 05 22
and one like this:
location position
6 1
7 1
8 2
9 2
10 2
11 3
12 3
How do I normalize the above so that given a location and a weight, I can find the value for a given position?
I can use Perl, Python, Excel, MySQL or pretty much any tool on the block to do the actual reshuffling of the data; where I'm having a problem is in coming up with a reasonable schema.
The desired outcome here is something like
if location == 11 -> position is 3
therefore,
if weight == 2 -> the value is 45
The only thing to do is "unpivot" your first table to this:
weight position value
1 1 10
1 2 20
1 3 30
2 1 25
2 2 35
2 3 45
3 1 17
3 2 05
3 3 22
The first two columns should contain unique pairs of values. If you have other information that only depends on weight, you would need another table for that. Same for positions.
Converting to the new model
If you already have the tables, then you can create the first table (t1) with this statement:
create table t1_new
select weight, 1 as position, position1 as value
from t1
union all
select weight, 2 as position, position2 as value
from t1
union all
select weight, 3 as position, position3 as value
from t1
Then, after verification of the result, drop t1, and rename t1_new to t1.
Querying from the new model
To query from these tables the value for a given location and weight, you should use a join:
select value
from t1
inner join t2 on t2.weight = t1.weight
where t2.location = 11
and t1.position = 3
i have a table with 61 records, where the first are "atomic" identified with their ID, and the other ones are combinations of the first 19 records like this
id pi1 pi2 pi3
1 1
2 2
3 3
...
19 19
20 1 13
21 1 18
...
24 2 6
25 2 7
26 2 7 16
in a webpage i have a form where the user clicks in the buttons that correspond to the atomic records (e.g. choice 2 and 7). when the user submits, the backend should consider that the user pressed 2 and 7 and then the resulting set should be:
id
2
7
25
the 24th row shouldn't be on the result because the user didn't pressed it
to get the basic records, i think this should suffice
SELECT *
FROM table
WHERE id = 2
OR id = 7
if more options are pressed, the query would have more operators. but to access the complex combinations i don't know how to achieve it without getting unwanted records just because one of the options is present in one of the Pi's (pi1, pi2 or pi3)
It is really better to change your data structure to have a junction table -- one row per "new" id and one per related id. However, you have the three columns.
I think this is the logic you want:
select t.*
from table t
where id in (2, 7) or
(2 in (pi1, pi2, pi3) and
7 in (pi1, pi2, pi3)
);
However, this will give you id 26 as well. Excluding that requires a bit more work. In MySQL, this should do the trick:
select t.*
from table t
where id in (2, 7) or
((2 in (pi1, pi2, pi3)) +
(7 in (pi1, pi2, pi3))
) = ((pi1 is not null) + (pi2 is not null) + (pi3 is not null))
At first I would like greet all Users and apologize for my english :).
I'm new user on this forum.
I have a question about MySQL queries.
I have table Items with let say 2 columns for example itemsID and ItemsQty.
itemsID ItemsQty
11 2
12 3
13 3
15 5
16 1
I need select itemsID but duplicated as many times as indicated in column ItemsQty.
itemsID ItemsQty
11 2
11 2
12 3
12 3
12 3
13 3
13 3
13 3
15 5
15 5
15 5
15 5
15 5
16 1
I tried that query:
SELECT items.itemsID, items.itemsQty
FROM base.items
LEFT OUTER JOIN
(
SELECT items.itemsQty AS Qty FROM base.items
) AS Numbers ON items.itemsQty <=Numbers.Qty
ORDER BY items.itemsID;
but it doesn't work correctly.
Thanks in advance for help.
SQL answer - Option 1
You need another table called numbers with the numbers 1 up to the maximum for ItemsQuantity
Table: NUMBERS
1
2
3
4
5
......
max number for ItemsQuantity
Then the following SELECT statement will work
SELECT ItemsID, ItemsQty
FROM originaltable
JOIN numbers
ON originaltable.ItemsQty >= numbers.number
ORDER BY ItemsID, number
See this fiddle -> you should always set-up a fiddle like this when you can - it makes everyone's life easier!!!
code answer - option 2
MySQL probably won't do what you want 'cleanly' without a second table (although some clever person might know how)
What is wrong with doing it with script?
Just run a SELECT itemsID, ItemsQty FROM table
Then when looping through the result just do (pseudo code as no language specified)
newArray = array(); // new array
While Rows Returned from database{ //loop all rows returned
loop number of times in column 'ItemsQty'{
newArray -> add 'ItemsID'
}
}//end of while loop
This will give you a new array
0 => 11
1 => 11
2 => 12
3 => 12
4 => 12
5 => 13
etc.
Select DISTINCT items.itemsID, items.itemsQty From base.items left outer join (select items.itemsQty as Qty from base.items) As Numbers On items.itemsQty <=Numbers.Qty
order by items.itemsID;
Use DISTINCT to remove duplicates. Read more here - http://dev.mysql.com/doc/refman/5.0/en/select.html
It seems like I understood what you asked differently than everyone else so I hope I answer you question. What I would basically do is -
create a new table for those changes.
Create a mysql procedure which given a line in the original table add new lines to the new table - http://dev.mysql.com/doc/refman/5.6/en/loop.html
Run this procedure for each line in the original table.
try this to get distinct values from both columns
SELECT DISTINCT itemsID FROM items
UNION
SELECT DISTINCT itemsQty FROM items
This is driving me nuts, I'm sure it's rather simple but can't get it right.
Having a table holding ratevalues for different years:
Ratevaluetable
Year Value A Value B Value C
2009 10 15 20
2010 12 18 22
2011 14 21 25
Then I have another persontable:
User Time Price
john 2010 value B
Tina 2009 Value C
Bill 2011 Value C
Now what I need is to join the 2 tables so that I get the value in the Price column substituted with the data from the Ratevaluetable.
I can join on time on year, but the I don't know how to join to the Value fields?
This is not possible with your current database schema. Joins connect tables by matching column values; what you propose to do here is match a column value with a column name, which is impossible.
What would be possible is:
Table ValueTypes:
Id Description
1 Value A
2 Value B
3 Value C
Table RateValueTable:
Year ValueTypeId Value
2009 1 10
2009 2 15
2009 3 20
Table User:
User Time ValueTypeId
john 2009 2
Given the above schema, you could join User to RateValueTable in the obvious manner.
It is possible, but it's not really the best database design. You'd have to do a conditional statement to figure out which column of Ratevaluetable to get.
SELECT persontable.User, persontable.Time, CASE WHEN persontable.Price = 'value a' THEN `Ratevaluetable.Value A` WHEN persontable.Price = 'value b' THEN `Ratevaluetable.Value B` WHEN persontable.Price = 'value c' THEN `Ratevaluetable.Value C` AS 'price' FROM persontable, Ratevaluetable WHERE persontable.Time = Ratevaluetable.year