SQL USING LIKE IN JOIN - mysql

I have a table Books
NAME
A
B
C
and another Booksassignment
ID ASSIGNMENTTEXT
1 Book.Assigned.To:A
2 Book.Assigned.To:A
3 Book.Assigned.To:B
4 Book.Assigned.To:B
5 Book.Assigned.To:C
6 Book.Assigned.To:A
7 OtherText:A
I want to get how many books were assigned to each person e.g.
I should get
Person Bookcount
A 3
B 2
C 1
I ONLY WANT TO GET THOSE ROWS WHERE Book.Assigned.To:NAME
I have tried using substring but I cannot solve
Thanks,
Aiden

You could use inner join and group by
select a.Name, b.count(*)
from Books a
inner join Booksassignment b on b.ASSIGNMENTTEXT like concat('%:', a.NAME)
group by a.Name

CREATE TABLE #T(nAME varchar(25))
INSERT INTO #T
SELECT 'A' UNION ALL
SELECT 'B' UNION ALL
SELECT 'C'
CREATE TABLE #tt (Id int,Book Varchar(25),Name Varchar(255))
INSERT INTO #tt
SELECT 1,'Book.Assigned','A' UNION ALL
SELECT 2,'Book.Assigned','A' UNION ALL
SELECT 3,'Book.Assigned','B' UNION ALL
SELECT 4,'Book.Assigned','B' UNION ALL
SELECT 5,'Book.Assigned','C' UNION ALL
SELECT 6,'Book.Assigned','A'
SELECT #tt.Name,COUNT(#tt.Name) from #tt INNER JOIN #T
ON #t.Name=#tt.Name
GROUP BY #tt.Name

I tried it on Mysql :
SELECT CONCAT(SUBSTRING(o.ASSIGNMENTTEXT,-1) ,' ', COUNT(ASSIGNMENTTEXT) ) FROM Booksassignment AS o GROUP BY ASSIGNMENTTEXT

If length of name column is always 1, you can as the below:
SELECT
B.Name AS Person,
COUNT(1) Bookcount
FROM
Books B INNER JOIN
Booksassignment BA ON B.NAME = BA.RIGHT(ASSIGNMENTTEXT, 1)
GROUP BY
B.Name

If name is allways in the end of the ASSIGNMENTTEXT column use right function
select name, count(*) from Books b
inner join Booksassignment a on b.name like RIGHT(a.ASSIGNMENTTEXT, 1)
where ASSIGNMENTTEXT like 'Book.Assigned.To:%'
group by name
Update ANSWER
If you need first column to be "Book.Assigned.To:":
select ASSIGNMENTTEXT, count(*) from Books b
inner join Booksassignment a on b.name like RIGHT(a.ASSIGNMENTTEXT, 1)
where ASSIGNMENTTEXT like 'Book.Assigned.To:%'
group by ASSIGNMENTTEXT
Exemple:
with Books as (select * from ( select 'A' as name union select 'B' union select 'C' ) as b )
, Booksassignment as (
select * from (
select 1 as iD, 'Book.Assigned.To:A' ASSIGNMENTTEXT union
select 2, 'Book.Assigned.To:A' union
select 3, 'Book.Assigned.To:B' union
select 4, 'Book.Assigned.To:B' union
select 5, 'Book.Assigned.To:C' union
select 6, 'Book.Assigned.To:A'
) as c
)
select name, count(b.name) as ASSIGNMENTs from Books b
inner join Booksassignment a on b.name like RIGHT(a.ASSIGNMENTTEXT, 1)
group by name

Try this:
;WITH T AS
(
SELECT
Id,
REPLACE(AssignmentText,SUBSTRING(AssignmentText,0, CHARINDEX(':',AssignmentText,0)+1),'') AS AssignedName
FROM #tblBooksassignment
)
SELECT
B.Name,
COUNT(T.Id) AS 'PersonBookCount'
FROM T
INNER JOIN #tblBooks B ON B.Name=T.AssignedName
GROUP BY B.Name
Output:

i think something like this will work
SELECT B.NAME,
COUNT( * ) as Bookcount
FROM Books B
JOIN Booksassignment BA
ON B.NAME = SUBSTRING( BA.ASSIGNMENTTEXT, -1 )
AND BA.ASSIGNMENTTEXT LIKE 'Book.Assigned.To:%'
GROUP BY B.NAME

Related

Join two tables and show where it come from

I have two tables:
ID, actor, description....
FK_ID, other_description...
I will now join these two tables, so that I have the following result:
ID|actor|description|other_description
1, Bud Spencer, >MainDescription<, null
1, Bud Spencer, null, Other_Description1
1, Bud Spencer, null, Other_Description2
.....
How can I write my query?
Thank you.
if you need the value in the same row You can use a left join on id and fk_id
select a.ID, a.actor, a.description, b.other_description
from table1 as a
left join table2 as b on a.ID = b.FK_ID
if you need the distinct value in the same column you can use union
select ID, actor, description
from table1
union
select fk_ID, null, other_description
from table2
if you need all the value you can use union all
SELECT A.ID A.actor A.description B.other_description
FROM tableA A
INNER JOIN tableB B ON
A.ID = B.FK_ID
SELECT a.ID, a.actor, a.description, b.other_description
FROM DB1 a
JOIN DB2 b
on a.ID=b.FK_ID

SQL join table to selected records

Example:
SELECT SUM(SALARY) FROM (SELECT * FROM table1 WHERE id > 10) a LEFT JOIN table2 b on a.person = b.person
I want join table2 records only to (SELECT * FROM table1 WHERE id > 10) records, my example is not correct.
table1 contain 100mln records and I cant join table2 to all records I must use subquery
I'm assuming, you salary is not summing up correctly (you are getting more than you expect). This is because LEFT JOIN will leave NULL for the rowsthat doesn't have match in b.
For this SQL:
SELECT a.*, b.*
FROM (select * from (SELECT 123 AS Salary,
'Tom' AS person
UNION
SELECT 343 AS Salary,
'Bob' AS person
UNION
SELECT 877 AS Salary,
'Tom' AS person) as t where t.Salary > 123) a
LEFT JOIN (SELECT *
FROM (SELECT 'Tom' AS person,
1 AS id
UNION
SELECT 'Bob' AS person,
2 AS id) AS t
WHERE t.id = 1) AS b
ON a.person = b.person
you will have this output:
So INNER JOIN should work for you.
SELECT SUM(SALARY) FROM (SELECT * FROM table1 WHERE id > 10) a
LEFT JOIN table2 b on a.person = b.person
Hopefully this will get you going in the correct direction....
select sum(a.salary)
from table1 a
left join table2 b on a.person = b.person and b.salary_type = "something"
where a.id > 10
;

Optimize MySQL Query on Multiple NOT INs

Is there any way to optimize this sql statement?
Maybe joins or something?
SELECT id, name
FROM item
WHERE id NOT IN (
SELECT id
FROM itemlock
) AND id NOT IN (
SELECT id
FROM itemlog
)
Thanks
use LEFT JOIN
SELECT a.*
FROM item a
LEFT JOIN itemLock b
ON a.ID = b.ID
LEFT JOIN itemLog c
ON a.ID = c.ID
WHERE b.ID IS NULL AND
c.ID IS NULL
You can also use UNION, like below:
SELECT id, name FROM item
WHERE id NOT IN (
SELECT id FROM itemlock UNION SELECT id FROM itemlog
)
Try this:
SELECT id, NAME FROM item i
LEFT JOIN (SELECT id FROM itemlock
UNION
SELECT id FROM itemlog) AS A ON i.id = A.id
WHERE A.id IS NULL;

How to select last date in 2 record in Mysql

How to select last date in 2 records in Mysql ?
TABLE A
SID NAME Sex
1 Jam M
2 Da F
TABLE B
ID Title SID Date
1 A 1 2012-07-31 09:57:10
2 NULL 1 2012-07-31 09:57:13
3 A 2 2012-07-31 10:10:13
4 NULL 2 2012-07-31 10:57:13
I want to inner join those two tables,
but select only one record only of Table B(distinct of SID) where title not null then show the
biggest Date of title is null field.
Result want the biggest Date of Null title:
ID Name Title SID Date
1 Jam A 1 **2012-07-31 09:57:13**
2 DA A 2 **2012-07-31 10:57:13**
How to do that ?
SELECT b.ID, a.NAME, b.Title, b.SID, b.Datea
from tablea a left outer join
(( SELECT sid, MAX(datea) AS latest
FROM tableb
where title is not null
GROUP BY sid) AS dt
INNER JOIN tableb b ON b.sid= dt.sid and b.datea=dt.latest )
on a.sid=b.sid
I think something like this will work for you:
SELECT b.ID, a.NAME, b.Title, b.SID, b.Date
FROM TABLEA a
INNER JOIN (SELECT SID, IFNULL(Title, "") AS Title,
MAX(IF(Title IS NULL, Date, NULL)) Date
FROM TABLEB GROUP BY SID) b
ON a.SID = b,SID;
Try my code (it works):
SELECT b.id, b.title, b.sid, b.date
FROM table_b as b
JOIN table_a as a ON a.sid = b.sid
WHERE b.id in (SELECT MAX(id) FROM table_b GROUP BY sid)

Complex MySQL query using group by

Lets say i have two tables
Table1:
product_id, design1, design2
1 A C
2 B A
Table2:
product_id, value
1 10
2 10
Now i want to to sum all the value for particular design for all products.
SELECT designA, SUM(value) FROM (
SELECT b.design1 AS designA, SUM(value) AS value FROM table2 AS a LEFT JOIN table1 AS b ON a.product_id = b.product_id GROUP BY b.design1) AS T GROUP BY designA
It gives me this:
designA SUM(value)
A 10
B 10
Now the problem is that if user has specified design2 in table1 then what ever is the value of design1 will automatically be added in design2. If design2 is not present design1 column then it will be a new row of result:
Desited result is this:
designA SUM(value)
A 20
B 10
C 10
select y.designA, sum(value) from
(select a.design1 as designA, value from
Table1 as a
inner join Table2 as b
on
a.product_id = b.product_id
union all
select a.design2 as designA, value from
Table1 as a
inner join Table2 as b
on
a.product_id = b.product_id) as y
group by y.designA
seems to work for your test data, not tried on other configurations but you should be able to tweak it, if you understand what it's doing.
UNION in the matches based on design2:
SELECT designA, SUM(value) FROM (
SELECT b.design1 AS designA, SUM(value) AS value FROM table2 AS a LEFT JOIN table1 AS b ON a.product_id = b.product_id GROUP BY b.design1
UNION
SELECT b.design2 AS designA, SUM(value) AS value FROM table2 AS a LEFT JOIN table1 AS b ON a.product_id = b.product_id GROUP BY b.design2
) AS T GROUP BY designA