Query giving undesirable results - mysql

I have the following two tables:
lab_assistant
la_id - la_firstname - la_lastname
1 - Dennis - Rodman
2 - Michael - Jordan
3 - Horace - Grant
hours_worked
hw_semester - hw_date - hw_hours - la_id
Fall 2012 - 2012-11-01 - 4 - 2
Fall 2012 - 2012-11-04 - 5 - 3
Spring 2012 - 2012-02-12 - 4 - 1
Spring 2012 -2012-03-10 - 4 - 1
The result of my query is supposed to look like the following:
and I'm trying to run the following query in order to list the Lab Assistant and the number of hours they worked each semester
SELECT DISTINCT(CONCAT(la.la_firstname, ' ', la.la_lastname)) AS 'Lab Assistant',
hw.hw_semester AS 'Semester Worked', hw.hw_hours AS 'Hours Worked'
FROM lab_assistant la
JOIN hours_worked hw
ON la.la_id = hw.la_id;
The results of my quere are SUPPOSED to look like this:
Michael Jordan - Fall 2012 - 4
Horace Grant - Spring 2012 - 5
Dennis Rodman - Fall 2012 - 8
BUT the results I'm getting are as follows:
Michael Jordan - Fall 2012 - 4
Horace Grant - Fall 2012 - 5
Dennis Rodman - Spring 2012 - 4
So basically, it just isn't counting the proper hours for Dennis Rodman. It should be 8 and not 4.
And I probably shouldn't use DISTINCT here because it's possible the same person could work different semesters.

DISTINCT needs to go at the beginning of the SELECT:
SELECT DISTINCT CONCAT(la.la_firstname, ' ', la.la_lastname) AS 'Lab Assistant',
hw.hw_semester, COUNT(w.hw_hours)
FROM lab_assistant la
JOIN hours_worked hw
ON la.la_id = hw.la_id;
But since you are using aggregate functions, you will want to use GROUP BY:
SELECT CONCAT(la.la_firstname, ' ', la.la_lastname) AS 'Lab Assistant',
hw.hw_semester, COUNT(w.hw_hours)
FROM lab_assistant la
JOIN hours_worked hw
ON la.la_id = hw.la_id
GROUP BY hw.hw_semester;
Based on your edit, you need something like this:
SELECT CONCAT(la.la_firstname, ' ', la.la_lastname) AS 'Lab Assistant',
hw.hw_semester AS 'Semester Worked',
sum(hw.hw_hours) AS 'Hours Worked'
FROM lab_assistant la
JOIN hours_worked hw
ON la.la_id = hw.la_id
GROUP BY la.la_id, hw.hw_semester;
See SQL Fiddle with Demo
Results:
| LAB ASSISTANT | SEMESTER WORKED | HOURS WORKED |
---------------------------------------------------
| Dennis Rodman | Spring 2012 | 8 |
| Michael Jordan | Fall 2012 | 4 |
| Horace Grant | Fall 2012 | 5 |

This is because DISTINCT is a modifier to SELECT and cannot be used like that. What's best in your case is to apply a GROUP BY on hw.hw_semester to fix it.

The MySQL syntax for SELECT shows that DISTINCT needs to come before the column names:
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[ .. etc .. ]
select_expr [, select_expr ...]
Each select_expr indicates a column that you want to retrieve.
Basically, DISTINCT can only apply to the entire query, not a single column.

Related

how to join two tables without duplicates in either side using mysql

I have two tables A and B for joining, with a common column at both tables. But the ID in both the tables are not unique, so it may have multiple rows in each table with same id.
Table A:
OFF_ID
OFF_NAME
YEAR
1
abc_tech
4yrs
2
def_tech
6yrs
3
ghi_tech
2yrs
4
xyz_tech
10yrs
5
lmn_tech
14yrs
Table B:
ID
NAME
DOB
CITY
1
George
2001
chennai
1
paul
2005
bangalore
1
hem
1997
mumbai
2
vasanth
1997
kerala
2
vicky
1997
gujarat
3
narayan
1997
kerala
I require an output in which the multiple row ID should display once and remain empty for other rows.
output required:
OFFICE_ID
OFFICE_NAME
YEAR
ID
NAME
DOB
CITY
1
abc_tech
4yrs
1
george
2001
chennai
-
-
-
1
paul
2005
bangalore
-
-
-
1
hem
1997
mumbai
2
def_tech
6yrs
2
vasanth
1997
kerala
-
-
-
2
vicky
1997
gujarat
3
ghi_tech
2yrs
3
narayan
1997
kerala
4
xyz_tech
10yrs
-
-
-
-
5
lmn_tech
14yrs
-
-
-
-
it will be helpful for me if i get query as mysql query.
Thanks in advance.**
If I get you right, the output you want as described in your last code block can hardly be achieved via mysql. Where do you want to output it? When you loop over your output, you can take care of it at that point.
SELECT * FROM table1 LEFT JOIN table2 on table1.id = table2.id

How to group after two fields and concatenate information from third field in query

I want to group data in ONE table after two columns (Numbers) and concatenate the information from a third column (short text) for the grouped results.
I am a non programming end user of Access with only little experience in SQL and no experience in VBA but I managed to follow the steps in this other question which already gets me half way to solving my own problem.
Concatenate multiple rows in one field in Access?
That´s why I will reuse the example data used in that post.
One probably just needs to tweak the code slightly for everything to work as intended.
The slightly changed example data from a referenced question looks like this:
Table "YourTable"
Year | Order Number | Product Types
2014 | 100001 | TV
2014 | 100001 | Phone
2016 | 100001 | Internet
2014 | 100002 | Phone
2014 | 100002 | Phone
2014 | 100003 | TV
2014 | 100003 | Internet
2015 | 100003 | Phone
2015 | 100003 | Notebook
For each available combination of Year and OrderNumber I want all corresponding differing entries in the column "product Types" listed separated by a slash or semicolon.
To do this for only one column to group by (Order Number) you can find the solution under the above linked question in the answer by HansUp:
https://stackoverflow.com/a/12428291/3954188
He uses the function "Concatenate values from related records" provided by Allen Browne to achieve the desired result and also provides the final query as an example. Everything works fine for grouping after one column using these resources.
How would I modify the query to get it working the way I´d like it to or is this impossible and needs another solution?
Please post the modified function code and/or query if possible. I managed to implement the function and the example solution from the other question but I´m not well versed in using SQL or VBA.
(I´m using Win 7, 64bit and MS Office 2013)
Include Year and Order Number in your query's GROUP BY. Then you want to concatenate the Product Types values within each of those groups.
I stored your sample data in an Access 2010 table named YourTable. With those data, this is the output from the query below ...
Year Order Number Expr1
---- ------------ --------------
2014 100001 Phone;TV
2014 100002 Phone;Phone
2014 100003 Internet;TV
2015 100003 Notebook;Phone
2016 100001 Internet
SELECT
y.Year,
y.[Order Number],
ConcatRelated
(
'[Product Types]',
'YourTable',
'[Year]=' & y.Year & ' AND [Order Number]=' & y.[Order Number],
'[Product Types]',
';'
) AS Expr1
FROM YourTable AS y
GROUP BY
y.Year,
y.[Order Number];
YOU CAN GET IT using following SQL (ON MYSQL)
SELECT Year , Order Number ,GROUP_CONCAT( Product Types) FROM TABLE GROUP BY Year , Order Number

Extract date from string in MySQL

I have columns of string data formatted like this:
Katy Perry Tickets - Staples Center. 09/19/2014 7:30 PM. 209 11
Atlanta Braves Tickets vs Miami Marlins Tickets - Turner Field. 08/31/2014 5:10 PM. 411L 2
I need to extract the date value from each field, and the common format is looking at the first full stop from the right until the next full stop. The date is always between those two.
A full stop occassionally occurs in the text to the left of the date so we can't trust that.
How can I get that particular substring? SQL gurus, your advice needed...
Thanks.
Try using Substring_Index
Select Substring_Index(Substring_Index( txt, ".", -2), ".", 1)
From Tablename
You can use the PREG functions for mysql , I have installed the UDF functions and I get this:
1- Creating and inserting sample data:
create table your_table (
txt_col text
);
insert into your_table values
('Katy Perry Tickets - Staples Center. 09/19/2014 7:30 PM. 209 11'),
('Atlanta Braves Tickets vs Miami Marlins Tickets - Turner Field. 08/31/2014 5:10 PM. 411L 2');
2- Testing the PREG_CAPTURE function using a pattern for dates:
mysql> SELECT PREG_CAPTURE(
'/([0-9]+\\/[0-9]+\\/[0-9]+)\\s[0-9]+:[0-9]+\\s[a-z]+/i' ,
txt_col, 0 ) as date_captured,
txt_col from your_table;
+--------------------+--------------------------------------------------------------------------------------------+
| date_captured | txt_col |
+--------------------+--------------------------------------------------------------------------------------------+
| 09/19/2014 7:30 PM | Katy Perry Tickets - Staples Center. 09/19/2014 7:30 PM. 209 11 |
| 08/31/2014 5:10 PM | Atlanta Braves Tickets vs Miami Marlins Tickets - Turner Field. 08/31/2014 5:10 PM. 411L 2 |
+--------------------+--------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
date_captured column is the extracted text.

Finding dates within one year of each other

I am trying to determine the number of employees who left the company within 1 year of being hired:
SELECT
Min(O896IA_VEMPPRSA.EMP_RHR_DT) AS MinOfEMP_RHR_DT,
Max(O867IA_VJOBHST.REC_EFF_STT_DT) AS MaxOfREC_EFF_STT_DT,
O896IA_VEMPPRSA.SYS_EMP_ID_NR
FROM O896IA_VEMPPRSA
INNER JOIN O867IA_VJOBHST
ON O896IA_VEMPPRSA.SYS_EMP_ID_NR = O867IA_VJOBHST.SYS_EMP_ID_NR
WHERE
O867IA_VJOBHST.EMP_ACN_TYP_CD="TER"
GROUP BY
O896IA_VEMPPRSA.SYS_EMP_ID_NR;
EMP_RHR_DT is the original hire date, and REC_EFF_STT_DT is the date they quit/were fired. Again I need the REC_EFF_STT_DT to be within 365 days of the EMP_RHR_DT. Any thoughts?
Example of RHR Date Changes. IN some cases there will only be one job but still a negative days worked, in other cases it is because it is selecting the wrong job.
Job MinOfEMP_RHR_DT MaxOfREC_EFF_STT_DT daysworked SYS_EMP_ID_NR
abc1 10/24/2012 4/15/2013 173 123456
abc1 4/25/2013 4/13/2013 -12 234567
abc3 7/8/2013 1/4/2013 -185 891234
abc4 7/8/2013 7/29/2013 21 891234
Assuming O896IA_VEMPPRSA is master table and O867IA_VJOBHST is detail table with the following data:
O896IA_VEMPPRSA:
ID EMP_RHR_DT SYS_EMP_ID_NR Empname
1 8/10/2012 1 John
2 10/10/2012 2 Matthew
O867IA_VJOBHST:
ID SYS_EMP_ID_NR EMP_ACN_TYP_CD REC_EFF_STT_DT
1 1 Married 1/1/2003
2 1 Became dad 8/1/2003
3 1 TER 9/10/2013
5 2 Remarried 1/1/2003
6 2 Remarried 8/1/2003
7 2 TER 9/10/2013
You could do this to get the number of days worked:
SELECT
Min(O896IA_VEMPPRSA.EMP_RHR_DT) AS MinOfEMP_RHR_DT,
Max(O867IA_VJOBHST.REC_EFF_STT_DT) AS MaxOfREC_EFF_STT_DT,
Max(O867IA_VJOBHST.REC_EFF_STT_DT) - Min(O896IA_VEMPPRSA.EMP_RHR_DT) as daysworked,
O896IA_VEMPPRSA.SYS_EMP_ID_NR
FROM O896IA_VEMPPRSA
INNER JOIN O867IA_VJOBHST
ON O896IA_VEMPPRSA.SYS_EMP_ID_NR = O867IA_VJOBHST.SYS_EMP_ID_NR
WHERE
O867IA_VJOBHST.EMP_ACN_TYP_CD="TER"
GROUP BY
O896IA_VEMPPRSA.SYS_EMP_ID_NR;
HAVING
(Max(O867IA_VJOBHST.REC_EFF_STT_DT) - Min(O896IA_VEMPPRSA.EMP_RHR_DT)) < 365;
The solution is with the datediff function. You will end up with a constraint like:
WHERE DateDiff("yyyy",hiringDate, endingDate)<1
Please check the exact syntax for the DateDiff function in the MS-Access help

Dynamically change database due to WHERE MySQL Crystal Reports

I'm programming with .NET 4.5, VS 2012 with CrystalReports in and MySQL (the last ^^).
I have 3 or more tables named like "rp31_bla_2012_bla" or "rp31_bla_2013_bla" or ...
Imagine you have a table with this:
- Name - Age - Job - Year -
Robert - 45 - Doctor - 2001
Robert - 45 - Housemade- 2002
Robert - 45 - Geek - 2006
Robert - 45 - Cooker - 2009
Robert - 45 - (null) - 2013
Nadège - 21 - CallGirl - 2001
Nadège - 21 - (null) - 2002
Nadège - 21 - CallGirl - 2008
Nadège - 21 - Home - 2008
Now I have a WinForm with two textBox, if the user writes "Robert" and "2013" I have to make a report with the "rp31_bla_***2013***_bla" WHERE Name = Robert.
Is it possible?
Which type of report should I create?
How can I change dynamically the query?
You can use union to combine the 3 tables and filter by name
SELECT * FROM
(
SELECT ..., 2012 as Year FROM rp31_bla_2012_bla
UNION
SELECT ..., 2013 as Year FROM rp31_bla_2013_bla
UNION
SELECT ..., 2014 as Year FROM rp31_bla_2014_bla
) t
WHERE t.Year =2013 and t.Name ='Robert'
Since the datasource will never change you don't need to to switch the tables.
This approach will be slower because you will always query the 3 tables
Another option will be to use a command in Crystal reports and to create a dynamic query which will be executed using exec -then you will be able to query just one table but you will need to handle special characters in the name ( like '%?)