inserting between condition in sum condition - mysql

HAVING SUM (DECODE (account_number, '1', 1, 0)) > :p_num_to
I want to integrate between condition into sum condition, user will enter two variables :p_num_from and p:_num_to.

Simply add another condition with AND
HAVING (SUM (DECODE (account_number, '1', 1, 0)) <p_num_to)
AND (SUM (DECODE (account_number, '1', 1, 0))>p_num_from)

Related

The query returns wrong result when i want to find who is the shortest player in a NBA Database

I am working with a NBA script in MySQL and I have to find out who is the shortest player in database. I am using feet as measurement and after executing the query i found out that the player the query was giving me was not the right answer.
The query is
select * from players where height=(select min(height) from players);
And it gaves me:
'420', 'Carlos Arroyo', 'Florida International', ' 6-2', '202', 'G', 'Magic'
where 6-2 is the height.
Instead of giving me one of these results
'26', 'Brevin Knight', 'Stanford', '5-10', '170', 'G', 'Clippers'
'113', 'Nate Robinson', 'Washington', '5-9', '180', 'G', 'Knicks'
'182', 'Earl Boykins', 'Eastern michigan', '5-5', '133', 'G', 'Bobcats'
'372', 'Damon Stoudamire', 'Arizona', '5-10', '171', 'G', 'Spurs'
'482', 'Chucky Atkins', 'South Florida', '5-11', '185', 'G', 'Nuggets'
And if I order by height players, the result it's a bit annoying:
'Carlos Arroyo', ' 6-2'
'Shareef Abdur-Rahim', ' 6-9'
'Louis Amundson', ' 6-9'
'Brevin Knight', '5-10'
'Damon Stoudamire', '5-10'
'Chucky Atkins', '5-11'
'Earl Boykins', '5-5'
'Nate Robinson', '5-9'
'Aaron Brooks', '6-0'
'Allen Iverson', '6-0'
'Kyle Lowry', '6-0'
'Jammer Nelson', '6-0'
'Sebastian Telfair', '6-0'
'Chris Paul', '6-0'
Convert the height-string to a number which you can use for numeric comparison.
select player, height
from players
where cast(substring_index(height, '-', 1) as unsigned)*100+
cast(right(concat('0', substring_index(height, '-', -1)),2) as unsigned)
in (
select min(cast(substring_index(height, '-', 1) as unsigned)*100+
cast(right(concat('0', substring_index(height, '-', -1)),2) as unsigned))
from players
)
See dbfiddle
...
where 6-2 is the height. Instead of giving me one of these results
...
You tell that all values '5-xx' are equivalent to each other, i.e. only value before the dash is taken into account.
Also you tell that you need in only one output row, and any row of shown 5 rows matches - i.e. you do not need in secondary sorting.
If so then you may simply do
SELECT *
FROM players
ORDER BY CAST(height AS UNSIGNED) LIMIT 1

MySql on Duplicate Key Update returning the table modified

I am trying to use ON DUPLICATE KEY UPDATE but returning the results which were changed
INSERT INTO `tableName` (`a`,`b`,`c`) VALUES (1,2,3),(4,5,6),(7,8,9)
ON DUPLICATE KEY UPDATE `a`=VALUES(`a`), `b`=VALUES(`b`), `c`=VALUES(`c`);
Is it possible to return for each row where there was an update what was the old value and with what value was replaced?
for example, if the original table contains
a
b
c
1
q
w
4
a
6
7
8
x
The Sql return to be something like a JSON
{1 : {'b' (column name): {'from': 'q', 'to': '2'}, 'c' (column name) : {'from': 'w', 'to': '3' }},
2 : {'b': {'from': 'a', 'to': '5'}},
3 : {'c': {'from': 'x', 'to': '9'}}}
There may be situations in which one update can update multiple rows, in this case, just the first one should be returned (or all of them if is complicated to implement)
Is there any magic that I can do to return the above JSON or any other format but with the correct data?
LATER EDIT:
I have created a new column and I am saving in it the old value
INSERT INTO `table`(
`a`,
`b`,
`c`,
`d`
)
VALUES(1, 7, 'us', null),(6, 8, 'us', null)
ON DUPLICATE KEY
UPDATE
`d` = CASE WHEN `b` = VALUES(`b`) THEN `d` ELSE `b`
END,
`b` = VALUES(`b`),
`c` = VALUES(`c`);
Having this column (with the old value) and not taking in consideration my initial request above (the JSON fromated response), is it possible to return all the rows in which I have a d (column) value taking in consideration that there may be other queries updating other rows in the table? and if yes, how can I do it, and how can I revert the d column to a null value keeping tha values which were in the db?

How to normalize column values in new column?

I've below data in table, val1,val2,val3 are of double type. x represents record is having old value and y represents new value. So we need to concatenate all double values in respective col (oldVal,newVal) based on x and y value
ID,region,status,val1,val2,val3
1, aa, x, 10, 11, 13
1, aa, y, 12, 14, 15
2, bb, x, null, null, null
2, bb, y, null, null, null
expected output, oldVal,newVal are of varchar type
ID,region,oldVal,newVal
1, aa,10-11-13, 12-14-15
1, bb,null, null
how to de-normalize can be done for this to get expected output ?
Note: If any of the value is null out of (val1, val2, val3), then null value should not be considered.
1,2,null > 1-2
You can try to use the condition aggregate function with CONCAT_WS function.
SELECT ID,
region,
MAX(CASE WHEN status = 'x' THEN CONCAT_WS('-',val1,val2,val3) END) oldVal,
MAX(CASE WHEN status = 'y' THEN CONCAT_WS('-',val1,val2,val3) END) newVal
FROM T
GROUP BY ID,region
sqlfiddle

List of tuples with strings not all arguments converted during string formatting

I am trying to insert hundreds of rows into a MySQL db at once. There are two types of records, unanswered calls and answered calls. I am putting all records into a list of tuples, and each record is it's own tuple, so that I can use the executemany function. I am getting a TypeError: not all arguments converted during string formatting, and I don't understand why.
answered = []
unanswered = []
insertQuery = """ INSERT INTO cdr (recno, relcause, starttime, answertime, endtime, releasecausetext, releasecausecode, 1streleasedialog,
origtrunk, callingnumber, orighost, callednumber, desthost, origcallid, origremotepayloadip, origremotepayloadport,
origlocalpayloadip, origlocalpayloadport, termtrunk, termsourcenumber, termsourcehost, termdestnumber, termdesthostname,
termcallid, termremotepayloadip, termremotepayloadport, termlocalpayloadip, termlocalpayloadport, duration, postdialdelay,
ringtime, durationms, routetableused, origtidalias, termtidalias, termpddms, reasoncause, mappedcausecode, mappedreasoncause,
reasoncausetext, origmos, termmos) VALUES ('%s'); """
for y in cdrList:
#Check to make sure record does not exist
sqlQuery = "select * from cdr where recno = %d and origcallid = %s;" % (int(y[0]), y[13])
if cursor.execute(sqlQuery):
print("Record exists")
else:
if y[7]=='NA':
unanswered.append((y[0], y[5],extractSqlDate(y[6]), 'null', extractSqlDate(y[8]), y[10], y[11], y[12], y[13], y[15], y[16], y[17], y[18], y[19], y[20], y[21], y[22], y[23], y[32], y[34], y[35], y[36], y[37], y[38], y[39], y[40], y[41], y[42], y[53], y[54], y[55], y[56], y[60], y[66], y[67], y[71], y[78], y[79], y[80], y[81], y[85], y[88]))
else:
answered.append((y[0], y[5],extractSqlDate(y[6]), extractSqlDate(y[7]), extractSqlDate(y[8]), y[10], y[11], y[12], y[13], y[15], y[16], y[17], y[18], y[19], y[20], y[21], y[22], y[23], y[32], y[34], y[35], y[36], y[37], y[38], y[39], y[40], y[41], y[42], y[53], y[54], y[55], y[56], y[60], y[66], y[67], y[71], y[78], y[79], y[80], y[81], y[85], y[88]))
try:
print(answered)
cursor.executemany(insertQuery, answered)
cursor.executemany(insertQuery, unanswered)
db.commit()
print("Record inserted successfully")
except MySQLdb.Error as e:
print(e)
I have confirmed that each element in each tuple in the list is a string:
Successfully connected to database
/PATH/20190610/20190610-0015-1750147245-1750147250.cdr
[('1750147245', '0001', '2019-06-10 00:10:50', '2019-06-10 00:10:59', '2019-06-10 00:11:13', 'Normal BYE', ' 200', 'O', '001102', '+tn', 'ip', '+tn', 'ip', '273418599_83875291#ip', 'ip', '20530', 'ip', '11944', '000020', '+tn', 'ip', 'tn', 'ip', '4121333-0-2851866068#ip', 'ip', '16840', 'ip', '11946', '13', '1', '8', '13450', '50', 'C - Peerless C6933_04 Origin', 'P - Thirdlane 6', '1150', '', '200', '', '', '0', '0')]
I found the problem. The tuple was returning strings, so the insert query was trying to insert values like this: ''value''. I removed the ' around the %s, and, based on #jonrsharpe's comment, added %s for each other value, and it worked.

Compare two strings according to defined values in a query

I have to compare two string fields containing letters but not alphabetically.
I want to compare them according to this order :
"J" "L" "M" "N" "P" "Q" "R" "S" "T" "H" "V" "W" "Y" "Z"
So if I compare H with T, H will be greater than T (unlike alphabetically)
And if I test if a value is greater than 'H' (> 'H') I will get all the entries containing the values ("V" "W" "Y" "Z") (again, unlike alphabetical order)
How can I achieve this in one SQL query?
Thanks
SELECT *
FROM yourtable
WHERE
FIELD(col, 'J', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'H', 'V', 'W', 'Y', 'Z') >
FIELD('H', 'J', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'H', 'V', 'W', 'Y', 'Z')
^ your value
Or also:
SELECT *
FROM yourtable
WHERE
LOCATE(col, 'JLMNPQRSTHVWYZ')>
LOCATE('H', 'JLMNPQRSTHVWYZ')
Please see fiddle here.
You can do
SELECT ... FROM ... ORDER BY yourletterfield='J' DESC, yourletterfield='L' DESC, yourletterfield='M' DESC, ...
The equality operator will evaluate to "1" when it's true, "0" when false, so this should give you the desired order.
There's actually a FIELD() function that will make this a bit less verbose. See this article for details.
SELECT ... FROM ... ORDER BY FIELD(yourletterfield, 'J', 'L', 'M', ...)