compare column of two rows of same table in mysql - mysql

I have a table name player_history containing history of player. in this table having column player_id, Final_position,meeting_code,race_no and beaten_time. If a player stood a first or second position the time will be same there are meeting code one day and in each meeting code there are maximum 10 races.
I want to select those records where 1st and second position beaten time are not same.
player_id Meeting_Code race_no final_position beaten_time
1 0001 1 1 2
2 0001 1 2 2
1 0001 2 1 5
2 0001 2 2 6
... so on
Output should be:
player_id Meeting_Code race_no final_position beaten_time
1 0001 2 1 5
2 0001 2 2 6
Also if it is not correct I want to update records of first position only.

Let table name be Test. Try to put Self Join or something like this:
Select t1.player_id t1.Meeting_Code t1.race_no t1.final_position t1.beaten_time
From Test t1
LEFT JOIN Test t2 ON t1.beaten_time != t2.beaten_time.
Try like this. It might work.

Check this it will work
SELECT *
FROM table_name
GROUP BY player_id
HAVING count(beaten_time) = 1;

Try It:
select b.player_id,b.meeting_code,b.race_no,b.final_position,b.beaten_time
from player_history a,player_history b
where a.race_no = b.race_no and a.beaten_time != b.beaten_time;

Related

Normalizing data from a pair of CSV tables

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

SQL: how select all rows where a "count > 1" for certain fields

I have 1 table, that has records by date. I need to compare data from year 1 to year 2 (last year), but in some cases a few records in year 1 don't exist in year 2 and some in year 2 do not exist in year 1.
I only care about those that match. my structure is:
F_DATE F_TEXT1 F_TEXT2 F_NUMBER1 F_NUMBER2
2014-01-01 bob sue 19 12
2013-04-19 bob sue 12 11
2013-06-01 bob jane 5 6
2014-11-28 jane bob 4 4
2014-03-12 mike bob 8 1
so in the above example only care about the records that contain bob + sue.
I can identify records by concat(F_TEXT1,F_TEXT2) as f_compare to get bobsue i can then count on this field having count(*) > 1 but doing this doesn't work well because F_DATE is unique to the pairing, and F_NUMBER1 and F_NUMBER2 are fundamental for further processing.
I am joining to another table, which has a F_LABEL for the years and a Start Date (F_SDATE) and End Date (F_EDATE) column to provide a nice label for the years.
I am having difficulty getting my records into a query so i can the process them further.
I have tried to select everything i need - this query gives the extra records from year 1 and year 2. and i also select a F_DATE from T_SOMETABLE which is basically for config so this query can be updated to compare year 3 to 4 etc by changing F_SOMEVALUE.
SELECT F_LABEL, F_TEXT1, F_TEXT2, F_NUMBER1, F_NUMBER2, fix
FROM (
SELECT b.F_LABEL, a.F_TEXT1, a.F_TEXT2, a.F_HGOALS, a.F_AGOALS,
concat(F_HOME,'-',F_AWAY) as fix FROM all_records a, some_labels b
WHERE a.F_DATE > b.F_SDATE
AND a.F_DATE < b.F_EDATE
AND a.F_DATE > (SELECT F_DATE FROM T_SOMETABLE WHERE F_SOMEVALUE='1')
UNION ALL
SELECT F_LABEL, F_TEXT1, F_TEXT2, F_NUMBER1, F_NUMBER2,
concat(F_TEXT1,'-',F_AWAY) as fix
FROM all_records a, some_labels b
WHERE a.F_DATE > b.F_SDATE
AND a.F_DATE < b.F_EDATE
AND a.F_DATE > (SELECT F_DATE FROM T_SOMETABLE WHERE F_SOMEVALUE='2')
AND a.F_DATE < (SELECT F_DATE FROM T_SOMETABLE WHERE F_SOMEVALUE='1')
) z
ORDER BY F_TEXT1, F_TEXT2, F_LABEL
I can't get my head round select from year 2 where the concat (above) exists in year 1 and then selecting the F_LABEL, F_TEXT1, F_TEXT2, F_NUMBER1 and F_NUMBER2from both years into one table.
Can you help point me in the right direction?
Bonus points if this query can go into a VIEW (nested statements don't help here) so the query/table doesn't need to be recreated every time a new record is added.
The query needs to be perform well as the output would appear on a webpage.
It is difficult to give a precise answer but, in order to compare a year with the previous one, you need to join your table with itself (t1 and t2 below are two occurrences of yourtable), to form a query like this:
SELECT ...
FROM yourtable t1, yourtable t2
WHERE (t1.F_TEXT1 = t2.F_TEXT1
OR t1.F_TEXT2 = t2.F_TEXT2)
AND YEAR(t1.F_DATE) = YEAR(t2.F_DATE) - 1

MYSQL Can WHERE IN default to ALL if no rows returned

Have a existing table of results like this;
race_id race_num racer_id place
1 0 32 2
1 1 32 3
1 2 32 1
1 3 32 6
1 0 44 2
1 1 44 2
1 2 44 2
1 3 44 2
etc...
Have lots of PHP scripts that access this table output the results in a nice format.
Now I have a case where I need to output the results for only certain race_nums.
So I have created this table races_included.
race_view race_id race_num
Day 1 1 0
Day 1 1 1
Day 2 1 2
Day 2 1 3
And can use this query to get the right results.
SELECT racer_id, place from results WHERE race_id=1
AND race_num IN
(SELECT race_num FROM races_included WHERE race_id='1' AND race_view='Day 1')
This is great but I only need this feature for a few races and to have it work in a compatible mode for the simple case show all races. I need to add alot of rows to the races_included table. Like
race_view race_id race_num
All 1 0
All 1 1
All 1 2
All 1 3
95% of my races don't use the daily feature.
So I am looking for a way to change the query so that if for race 1 there are no records in the races_included table it defaults to all races. In addition I need it to be close the same execution speed as the query without the IN clause, because this query Or variations of it are used a lot.
One way that does work is to redefine the table as races_excluded and use NOT IN. This works great but is a pain to manage the table when races are added or deleted.
Is there a simple way to use EXISTS and IN in tandem as a subquery to get the desired results? Or some other neat trick I am missing.
To clarify I have found a working but very slow solution.
SELECT * FROM race_results WHERE race_id=1
AND FIND_IN_SET(race_num, (SELECT IF((SELECT Count(*) FROM races_excluded
WHERE rid=1>0),(SELECT GROUP_CONCAT(rnum) FROM races_excluded
WHERE rid=1 AND race_view='Day 1' GROUP BY rid),race_num)))
It basically checks if any records exists for that race_id and if not return a set equal to the current race_num and if yes returns a list of included race nums.
You can do this by using or in the subquery:
SELECT racer_id, plac
from results
WHERE race_id = 1 AND
race_num IN (SELECT race_num
FROM races_included
WHERE race_id = '1' AND (race_view = 'Day 1' or raw_view = 'ANY')
);

MySQL where condition when intersecting 2 values (comma delimited)

I have table like this:
id products
------ ----------
5 1,2,3
6 2,4,5
9 1,4,7
17 4,6,7
18 1,6,8
19 2,3,6
I have to select only that rows, which row's products column contains one of (2,3) values.
In this case query must return:
id products
------ ----------
5 1,2,3
6 2,4,5
19 2,3,6
But I don't understand how to make construction of this query.
Any ideas?
Thanks in advance.
SELECT id,products
FROM yourTable
WHERE FIND_IN_SET('2',products)>0
OR FIND_IN_SET('3',products)>0
sqlFiddle
Would you mind to try this one please?
select * from TABLE_NAME where products regexp "(^|,)[23](,|$)";
Its doing either two or three at the begining, or at end. Or in between the commas.
Never, never, never store multiple values in one column.
Like you see now this will only give you headaches. Normalize your table. Then you can select normally.
Your table should look like this
id product
-- -------
5 1
5 2
5 3
6 2
6 4
6 5
...
With that table structure your select would be
select id
from your_normalized_table
where product in (2,3)
group by id
having count(distinct product) = 2
That query can make use of indexes and is really fast.

tsql Update with where

Currently my worktable looks like this:
Portfolio SEDOL Grouped Level
1 111 As Primary 2
1 111 Energy 2
1 122 Financial 2
2 111 Financial 1
2 133 As Primary 1
2 133 Gas 1
2 123 Oil 1
Basically what i want to do is update the worktable where grouped = "As Primary". You will see that the As Primary record has the same SEDOL as the Primary that it should match to. It has to match on the level as well as it is possible for a portfolio to only hold the secondary so will have to match on a portfolio with the same level so that there is no error.
I was guessing that the script would have to look something like this:
UPDATE #WorkTable
SET Grouped = (SELECT Grouped FROM #Worktable
WHERE ...............
WHERE (Select .............
But i'm getting confused as to what to put in my selects. A point in the right direction would be great.
Thanks
You can do this using UPDATE with JOIN. Something like this:
UPDATE t1
SET t1.Grouped = t2.Grouped
FROM #WorkTable t1
INNER JOIN #Worktable t2 ON -- a condition
WHERE -- you can also add conditions here