I have two tables, donaTypes and fullInfo.
fullInfo:
id funddesc giftamt giftdate
001 annual fund 50.00 2010-03-09
223 alumni fund 25.00 2009-03-06
334 capital exp 100.00 2011-09-27
... ... ... ...
donaTypes:
id donaType
1 annual fund
2 capital exp
3 alumni fund
I'm trying to match up where fullInfo.funddesc = donaTypes.donaType with the hope of inserting the donaTypes.id number into the fullInfo table. Here's my code but I just get a blank response (no error):
SELECT st1.funddesc, st2.donatype
FROM
(select t1.funddesc
from fullInfo as t1) st1
inner join
(select t2.donatype
from donatTypes as t2) st2
on trim(st1.funddesc) like trim(st2.donaType)
;
I also tried :
SELECT t1.funddesc, t2.donatype
FROM fullInfo as t1,
donatTypes as t2
where trim(t1.funddesc) = trim(t2.donatype);
Ideally, I'd like fullInfo to look like this:
fullInfo:
id funddesc giftamt giftdate
001 1 50.00 2010-03-09
223 3 25.00 2009-03-06
334 2 100.00 2011-09-27
... ... ... ...
Keep it a bit simpler til you get it debugged. You don't need the nested queries. And, LIKE is not really very good for joins, because it can be kind of promiscuous.
SELECT fi.funddesc, dt.donaType
FROM fullinfo fi
JOIN donatTypes dt on trim(fi.funddesc) = trim(dt.donaType)
You may also want to do this sort of thing on your two tables just to figure out what kind of stuff you actually have in your join columns.
SELECT COUNT(*), concat('>>>',TRIM(funddesc),'<<<')
FROM fullinfo
GROUP BY concat('>>>',TRIM(funddesc),'<<<')
Related
I have two tables which look like this:
ID
SOME_DATA_FIRST_TABLE
1
22
2
32
3
45
ID
SOME_DATA_SECOND_TABLE
1,2,3,4,5,6
99
5,6,7,8,9,11
31
56,67,88,45,11
87
How can I make a join between tables which would like:
SELECT *
FROM first_table as ft,
JOIN second_table as st,
on <if ft.ID (for example 1) is inside of the values in the column from the second table (for example 1,2,3,4,5,6) then it should make a join between tables.
How such a syntax should look like?
I couldn't find any similar thread, and couldn't find any solution to it.
It is better to normalize your data, the performance and database management would be better and easier.
As per the question you could use FIND_IN_SET:
select t1.ID,
t1.SOME_DATA_FIRST_TABLE,
t2.ID,
t2.SOME_DATA_SECOND_TABLE
from table1 t1
inner join table2 t2 ON FIND_IN_SET(t1.ID,t2.ID);
Result:
ID SOME_DATA_FIRST_TABLE ID SOME_DATA_SECOND_TABLE
1 22 1,2,3,4,5,6 99
2 32 1,2,3,4,5,6 99
3 45 1,2,3,4,5,6 99
Demo
table:tab1
id date_time zoneid accountid slotid trequest bidder width height
_50832 2017-09-04 15:41:06 153 1654 153x468x60 10 aaa 468 60
_50832 2017-09-04 15:41:06 152 1654 152x468x60 10 bbb 468 60
table:tab2
id date_time zoneid accountid slotid bidder count
_50832 2017-09-04 15:41:06 152 1654 152x468x60 bbb 6
_50832 2017-09-04 15:41:06 152 1654 152x468x60 bbb 4
_50832 2017-09-04 15:41:06 153 1654 153x468x60 aaa 9
_50832 2017-09-04 15:41:06 153 1654 153x468x60 aaa 1
below is my query:
SELECT SUM(req.trequest) as REQ, SUM(win.count) as IMP
FROM tab1 as req
JOIN tab2 as win ON (req.id=win.id AND req.zoneid=win.zoneid)
GROUP BY req.zoneid
I get below result,
REQ IMP
20 10
20 10
IMP count is correct but I get wrong REQ count. My expected result is
REQ IMP
10 10
10 10
How to get my expected result?
Lets find the sum of trequest and count separately based on zoneid and id.Then use these two results ( t1 and t2 ) in the inner join.
Count mismatch problem shown in the question occur due to multiple rows satisfying the joining conditions.
In this solution we will only have one entry for each zoneid in both the results ( t1 and t2 ). So the problem is avoided.
Note: You can remove the id column from the GROUP BY clause if it doesn't make any difference.
SELECT t1.id, t1.zoneid, t1.REQ, t2.IMP FROM
(SELECT id,zoneid,SUM(trequest) as REQ
FROM tab1 GROUP BY zoneid,id ) t1
INNER JOIN
(SELECT id,zoneid SUM(win.count) as IMP
FROM tab2 GROUP BY zoneid,id ) t2
ON t1.id = t2.id
AND t1.zoneid = t2.zoneid
Let's try first sumwin.count and group records in sub-query, after it join tables. Try in following:
SELECT SUM(req.trequest) as REQ, SUM(win.count) as IMP
FROM tab1 as req
JOIN (
SELECT SUM(win.count) as IMP, win.zoneid, win.id
FROM tab2 as win
GROUP BY win.zoneid, win.id) AS win ON req.id=win.id AND req.zoneid=win.zoneid
GROUP BY req.zoneid
Instead of req.zoneid. You should try win.zoneid. What seems is that the rows in table 1 are counted multiple times as zoneid in table 2 comes twice. So win.zoneid would group it and avoid the repetition.
Updated: The solution posted by #mayur panchal is the correct one as you don't need to SUM the rows in first table as they belong to different zoneid. If you SUM them you will obviously get the 20 repeated twice.
I try to use DISTINCT to avoid duplication of the data, but no work.
How to avoid the duplicate data?
Table 1
Employee code Deduction Voucher no Dec_Amount
001 999 50
001 888 20
002 777 100
Table 2
Employee code Payslip Voucher No Pay_Amount
001 111 100
002 222 200
The output should be:
Employee code Deduction Voucher no Dec_Amount Payslip Voucher No Pay_Amount
001 999 50 111 100
001 888 20
002 777 100 222 200
But i got the table like this.
Employee code Deduction Voucher no Dec_Amount Payslip Voucher No Pay_Amount
001 999 50 111 100
001 888 20 111 100
002 777 100 222 200
You cannot get those results with just a SQL query. It seems to me you need it in this format for display in a table/excel spreadsheet. If this is the case you would have to handle the "Hiding" of the particular entries with some other code. The reason is because the entries you want to hide are correctly associated with the 001 employee.
While I do agree this probably makes a lot more sense to do in your front end code, it is possible to do in SQL. Using a variable you get a function similar to SQL Server's ROW_NUMBER function and then only join on the first row per employee code.
See the sqlfiddle - http://sqlfiddle.com/#!2/47302/11
SELECT t1.`Employee code`,`Deduction Voucher no`,`Dec_Amount`,
COALESCE(`Payslip Voucher No`,'') as `Payslip Voucher No`,
COALESCE(CAST(`Pay_Amount` as char(10)),'') as `Pay_Amount`
FROM Table2 t2
RIGHT JOIN
(
SELECT #row_num := IF(#prev_value=`Employee code`,#row_num+1,1) AS RowNumber
,`Employee code`,`Deduction Voucher no`,`Dec_Amount`
,#prev_value := `Employee code`
FROM Table1,
(SELECT #row_num := 1) x,
(SELECT #prev_value := '') y
ORDER BY `Employee code`
) t1
ON t1.`Employee code`=t2.`Employee code` AND t1.RowNumber=1
To expand on #d.lanza38's answer, there is no way given for the DB to tell which row in table1 should get the data from table2. Remember that there is no order to the data in the database, so there is no inherent concept of "the first row with employee code 001".
A standard (inner) join will put them as you have shown - on both. Which is actually correct - your table structures say that for every payslip in table2, there can be many deductions. So if you want the data from both tables, the deductions have to have the matching payslip data attached.
You can't use DISTINCT to magically fix your data - you need to understand the data structures, and relate them correctly.
To get what is in your example (which may be wrong) try this SQL:
select
a.Employee_code,
Deduction_Voucher_no,
Dec_Amount,
Payslip_Voucher_No,
Pay_Amount
from
table1 as a
inner join table2 as b on a.employee_code = b.employee_code
where Deduction_Voucher_no = (
select max(Deduction_Voucher_no)
from table1 as c
where a.Employee_code = c.Employee_code)
UNION
select
a2.Employee_code,
Deduction_Voucher_no,
Dec_Amount,
null as Payslip_Voucher_No,
null as Pay_Amount
from
table1 as a2
inner join table2 as b2 on a2.employee_code = b2.employee_code
where Deduction_Voucher_no <> (
select max(Deduction_Voucher_no)
from table1 as c2
where a2.Employee_code = c2.Employee_code)
order by 1,2 desc
Note: untested, because I don't have your database, and don't even know which database engine you are using. If it complains about selecting nulls, replace with 0 or '' depending upon the data type.
UPDATE improved SQL and provided a fiddle: http://sqlfiddle.com/#!2/e7fc2/2
i have three tables in mysql like this,
triz_sti
stu_id name
-----------------
1 x1
2 x2
triz_sub
sub_id sub_name
------------------
1 english
2 maths
3 science
triz
stu_id sub_id marks
-------------------------
1 1 23
1 2 56
1 3 83
2 1 78
2 2 23
2 3 50
i want the result like
display all subject with higest mark in perticular subject with student name,
max_marks sub_name student_name
--------------------------------------
78 english x2
56 maths x1
83 science x2
so please help for this output that i want, i have tried but i m not get it desire output.
How about something like this?
SELECT
t.stu_id, t.sub_id, t.marks
FROM
triz t
JOIN (SELECT sub_id, MAX(marks) max_mark FROM triz GROUP BY sub_id) a ON (a.sub_id = t.sub_id AND a.max_mark = t.marks)
Of course you'll need to join it with lookup tables for names.
Have to say, it's early here so I might have missed something.
BR
The general, simplified syntax in this case is
SELECT stuff FROM joined tables ORDER BY whatever
The easiest is the ORDER BY: you want to sort descending by marks, so you ORDER BY marks DESC.
Where do the data come from? From triz, joined to the others. So
triz JOIN triz_sti USING (stu_id) JOIN triz_sub USING (sub_id)
And you want to display the marks.
So you get
SELECT marks, sub_name, name AS student_name
FROM triz JOIN triz_sti USING (stu_id) JOIN triz_sub USING (sub_id)
ORDER BY marks DESC
.
The rest I leave to you. :-)
In short words:
I have events table:
[tbl]
time | newState
1200 | 1
1300 | 2
1400 | 5
I need to transform this table into intervals table [intervals]:
t0 | t1 | state
1200 | 1300 | 1
1300 | 1400 | 2
RESTRICTION: SQL COMPACT EDITION
the query:
SELECT leftPart.time AS t0, min(rightPart.time) AS t1, leftPart.newState
FROM tbl AS leftPart
LEFT OUTER JOIN tbl As rightPart
ON leftPart.time<rightPart.time
GROUP BY leftPart.Time,leftPart.newState
It works perfect when [tbl] is permanent table in database, but in my case [tbl] is derived from another select subquery! like this:
(SELECT time,newState
from ...) AS derivedTb
So, when i try something like this:
SELECT derivedTbl.time As t0,derivedTbl.state,min(rigthTblPart.time) FROM
(SELECT time,newState
from ...) AS derivedTbl
LEFT OUTER JOIN with derivedTbl AS rigthTblPart
ON derivedTbl.Time<rightTblPart.Time ...
It throws error: "derivedTbl does not exist"...
It seems that the derived table under it's alias is not visible to higher level query (thanks, google translator! ))...
Is there any way to store derived tables in query and using them in different parts of query? SQL CE doesn't support temporary tables, views and common table expressions...
task details (if interesting):
i have 2 tables of events:
[states1]
time | state1
1200 | 1
1300 | 2
1400 | 3
[states2]
time | state2
1200 | 0
1230 | 10
1330 | 20
1430 | 30
I need convert them in intervals table:
[intervals]
t0 t1 state1 state2
1200 1230 1 0
1230 1300 1 10
1300 1330 2 10
1330 1400 2 20
1400 1430 3 20
1430 NULL 3 30
stages of convertion:
1. overall timeline
(SELECT Time FROM States1
UNION
SELECT Time FROM States2) AS timetbl
join states1 table
join states2 table
for this moment all goes well:
SELECT states12tbl.time, states12tbl.state1, states2tbl.State AS state2
FROM (SELECT states12tbl_1.time, states12tbl_1.state1, MAX(states2tbl.Time) AS states2time
FROM (SELECT timetbl.time, states1tbl.State AS state1
FROM (SELECT timetbl_1.Time AS time, MAX(States1tbl.Time) AS state1time
FROM (SELECT Time
FROM States1
UNION
SELECT Time
FROM States2) AS timetbl_1 LEFT OUTER JOIN
States1 AS States1tbl ON States1tbl.Time <= timetbl_1.Time
GROUP BY timetbl_1.Time) AS timetbl INNER JOIN
States1 AS states1tbl ON timetbl.state1time = states1tbl.Time
join table with itself... and here is problem, i need to join code(3) with itself, because sql ce can't remember temp tables... If you have some better idea, please, share :)
Create a VIEW based on your first SELECT.
Onotole, I think that this WITH is making the trouble.
rewrite this query like
SELECT
derivedTbl.time As t0,
derivedTbl.state,
min(rigthTblPart.time)
FROM
(SELECT time,newState from ...) AS derivedTbl
LEFT OUTER JOIN derivedTbl AS rigthTblPart
ON derivedTbl.Time<rightTblPart.Time
....