I am trying to execute a SQL query such that the following table:
id in_year out_year
------- ---------- -------------
1 2001 2002
2 2002 2002
3 2004 2007
can be queried such that I get all the years within that range mapped to the id. For instance, I would like to get:
id year
--------- ---------
1 2001
1 2002
2 2002
3 2004
3 2005
3 2006
3 2007
Specifically, lets say the table represents a shop with elements and their arrival to shop, and sell dates. The query would return all the element ids mapped to the year where they were in the shop.
You can construct a temp table with the years in your range of data i.e.
CREATE TABLE tmp_years (
yr YEAR NOT NULL,
PRIMARY KEY (yr)
) ENGINE=INNODB;
INSERT INTO tmp_years (yr) VALUES (2000), (2001), (2002), (2003), (2004), (2005), (2006), (2007);
and then do a JOIN:
SELECT w.id, y.yr FROM wesams_table w
INNER JOIN tmp_years y ON (y.yr >= w.in_year AND y.yr <= w.out_year);
The tidiest solution would be to create a UDF to return the range of years and use CROSS APPLY.
Performance should be rather good as the UDF will be deterministic
Edit: Sorry, I don't think this applies to MySQL.
Related
I have a table in the form:
id
comp
employment_year
1
ShoesCo
2000
1
FeetOrg
2006
1
SizeEight
2012
2
ShoesCo
2001
2
SizeEight
2004
2
FeetOrg
2007
3
SizeEight
2001
3
ShoesCo
2004
3
FeetOrg
2007
I want to count (get the total) number of people who worked at ShoesCo prior to (employment_date) working at SizeEight. The id is the uniqueid for each employee. I am thinking of self-join but have limited experience with SQL.
The answer should be 2 for this example.
If the data have no duplicates by (id,comp) then
SELECT COUNT(DISTINCT id)
FROM table t1
JOIN table t2 USING (id)
WHERE t1.comp = 'ShoesCo'
AND t2.comp = 'SizeEight'
AND t1.employment_year < t2.employment_year
I am currently working on a.Net web form solution which generates a brief service report for admins to monitor the services done by technicians.As of now , i am having some trouble in coming up with an efficient SQL (for MySQl) which return data rows along with the missing rows based on the SertvicePrtNum , which is in order.
For Example :-
This is my raw data in the table :-
Id ServiceRptNum Customer_ID Date of Service
---- ------------- ----------- ---------------
1 1001 3 09/10/1997
2 1003 8 10/06/2005
3 1005 1 21/02/2003
4 1007 7 1/06/2011
5 1010 4 4/11/2012
6 1002 2 16/01/2003
Here the ServiceRptNum , 1004 is missing in the table. So i want the db to return the result as : -
Id ServiceRptNum Customer_ID Date of Service
---- ------------- ----------- ---------------
1 1001 3 09/10/1997
2 1002 2 16/01/2003
3 1003 8 10/06/2005
- 1004 - -
4 1005 1 21/02/2003
- 1006 - -
5 1007 7 1/06/2011
- 1008 - -
- 1009 - -
6 1010 4 4/11/2012
Here , the sql additionally generated 1004,1006,1008,1009 since it cannot find those records.
Please note that the Id is automatically generated (auto_increment)while insert of the data.But the Service ReportNum is not , this is to enable the admin to add the service report later on with the manually generated report Num (report num in the hardcopy of the company Servicebook).
You basically need to invent a constant, sequential stream of numbers and then left join your real data to them. For this method to work, you need a table with enough rows in it to generate a counter big enough:
select ID, 1000+n as servicerptnum, customer_id, `Date of Service` from
(
SELECT #curRow := #curRow + 1 AS n
FROM somebigtable
JOIN (SELECT #curRow := 0) r
WHERE #curRow<100
) numbergen
LEFT JOIN
tablewithmissingservicerptnum
ON
servicerptnum = 1000+n
You need to alter some things in the code above because you never told us the name of your table with missing rptnums. You also need to utilise another table in your database with more rows than this table because the way this method works is to count the rows in the bigger table, giving each a number. If you don't have any table bigger than this one, we can probably get enough rows by cross joining a smaller table to itself or by using this table. Replace somebigtable with thistable CROSS JOIN thistable where this table is the name of the table with missing servicerptnums
If you want just the rows that are missing, add a WHERE servicerptnum is null to the end of the sql
Edit, I see you've changed your numbering from:
1001
1002
...
1009
10010
To:
1009
1010
The join condition used to be servicerptnum = concat('100', cast(n as varchar)), it is now servicerptnum = 1000+n..
Look here for ideas on how to generate a group of continuous integers, then select from that left outer join your table. You should get a row for every number but all the values will be null for the missing numbers.
I have created two tables employees_tab and devices_tab in MySQL work bench.
Devices_tab
Serial_No Device_ID Device_Name Level
1 2001 Desktop Computer 1
2 2001 Laptop 2
3 2001 Desktop Computer 3
employees_tab
Employee_ID Employee_Name Designation Password Level
1001 Nimal Manager 698d51a19d8a1211 1
1002 Kamal Accountant 2c0343a2395834dd 2
1003 Sunil Trainee f762a2aaa148d556bd 3
Now I need to take all devices which have according to level for each employee and create a new table. Also in each time that I insert new user to the employee table new table should be updated with that value.
How do i do that?
I use SQL joins. But i can't update that in each time the new table with using old tables
INSERT INTO table3(Device_Name,Employee_Name,Level)
SELECT t1.Device_Name,t2.Employee_Name,t2.Level
FROM Devices_tab t1
LEFT JOIN employees_tab t2 ON t1.Level=t2.Level
Try This Code.Not sure but you try give a idea.
I am creating a library database and have four tables as follows;
I have been researching ways to work out the frequency in MySQL but after such as long time and misunderstanding I've decided to try get an example of how to work out the frequency on tables that I'll understand. Below are the four tables I am currently using.
I am looking to workout the loan frequency of every book that has been loaned 2 or more times. By doing this I am able to see how working out frequency would work when selecting specific values instead of all values.
From looking at my tables I would have to select the 'code' from the loan table, select all values that occur twice or more and then workout the frequency of the occurrence.
From my research I would decide to use an INNER JOIN to connect the tables, COUNT to count the number of values, GROUP BY to group the values and HAVING as WHERE may not be used. I am having trouble writing the query and continuously stumble upon errors. Could anyone use the example above to explain how they worked out the frequency of each book loaned two times or more? Thanks in advance
Table 1 - book
isbn title author
111-2-33-444444-5 Pro JavaFX Dave Smith
222-3-44-555555-6 Oracle Systems Kate Roberts
333-4-55-666666-7 Expert jQuery Mike Smith
Table 2 - copy
code isbn duration
1011 111-2-33-444444-5 21
1012 111-2-33-444444-5 14
1013 111-2-33-444444-5 7
2011 222-3-44-555555-6 21
3011 333-4-55-666666-7 7
3012 333-4-55-666666-7 14
Table 3 - student
no name school embargo
2001 Mike CMP No
2002 Andy CMP Yes
2003 Sarah ENG No
2004 Karen ENG Yes
2005 Lucy BUE No
Table 4 - loan
code no taken due return
1011 2002 2015.01.10 2015.01.31 2015.01.31
1011 2002 2015.02.05 2015.02.26 2015.02.23
1011 2003 2015.05.10 2015.05.31
1013 2003 2014.03.02 2014.03.16 2014.03.10
1013 2002 2014.08.02 2014.08.16 2014.08.16
2011 2004 2013.02.01 2013.02.22 2013.02.20
3011 2002 2015.07.03 2015.07.10
3011 2005 2014.10.10 2014.10.17 2014.10.20
You didn't specify the type of frequency, but this query calculates the number of loans per week for each book that was loaned more than once in 2014:
select b.isbn
, b.title
, count(*) / 52 -- loans/week
from loan l
join copy c
on c.code = l.code
join book b
on b.isbn = c.isbn
where '2014-01-01' <= taken and taken < '2015-01-01'
group by
b.isbn
, b.title
having count(*) > 1 -- loaned more than once
I have several data series in a MySQL table.
The fields are Series, Date, Value. Is there a way for me to select, for two distinct Series, all the dates for which the series overlap and then for each date, the quotient of the value from series one and series two.
Example:
Series Date Value
Dogs 2004 10
Dogs 2005 12
Dogs 2006 14
Dogs 2007 16
Cats 2004 6
Cats 2005 6
Cats 2006 7
Cats 2007 4
I would like something like SELECT Cats/Dogs and get the following result
Date Value
2004 .6
2005 .5
2006 .5
2007 .25
You can achieve this with a self-join on your table.
SELECT cats.Series, cats.value / dogs.value
FROM animals cats
INNER JOIN animals dogs
ON dogs.Date = cats.Date
WHERE cats.Series = "Cats"
AND dogs.Series = "Dogs"
It would be preferable for performance to have an index on Date, and a key on (Series,Date) would be ideal.