I am new in Sql Could you please help it with this problem.
id |name |reportingTo
----------------------
1 A NULL
2 B 1
3 C 1
4 D 2
5 E 2
6 F 5
I want the expected output as below. How i can impliment this with one query.
Output
------------------------
Name Reporter
A No One
B A
C A
D B
E B
F E
I have tried this but not working
select name,(case when reporting = null then 'MD'
ELSE (select a.name from testLevel a inner join testLevel b on a.id=b.reporting where a.id=b.reporting)
END) reportingto
From testLevel
Thanks In-advance..
Keep joins and subselects out of your select statement.
MySQL and Oracle are two seperate databases...choose on or the other
select a.name, b.name
from reportingto a left join reportingto b on a.id = b.reportingto
that will give names..use a isnull statement to resolve the 'no one' when bnot found. Note the left join makes this possible, an inner join won't work here.
select a.name, isnull(b.name, 'No One')
from reportingto a left join reportingto b on a.id = b.reportingto
How about a self join? So something like
SELECT r.Name ,
rTo.Name Reporter
FROM testLevel r LEFT JOIN
testLevel rTo ON r.ReportingTo = rTo.id
Based on the fact that you have picked 3 RDBMSs you might want to take a look at
MySQL IFNULL:
IFNULL(rTo.Name, 'No One') Reporter
SQL Server ISNULL
ISNULL(rTo.Name, 'No One') Reporter
In SQL Server:
You can also achieve this by using a Common Table Expression:
WITH CTE (
SELECT DISTINCT reportingTo, name
FROM testLevel
)
SELECT DISTINCT A.name AS Name, ISNULL(B.name, 'No One') AS Reporter
FROM testLevel A
LEFT JOIN CTE B ON A.id = B.reportingTo
Or using a subquery:
SELECT DISTINCT A.name AS Name, ISNULL(B.name, 'No One') AS Reporter
FROM testLevel A
LEFT JOIN (
SELECT DISTINCT reportingTo, name
FROM testLevel
) B ON A.id = B.reportingTo
Related
I'm currently working on a filter form to display a set of products. The product name is located in TABLE a with the filter tags in TABLE b. As filters are selected, the query needs to return all products from table a that fits all criteria selected.
My current query is (this example has two filters selected):
SELECT a.genus
,a.botanical
FROM a
WHERE a.ID IN (
SELECT filter.filtered
FROM (
SELECT b.ID AS filtered
,COUNT(*) c
FROM b
WHERE b.tag_ID = 1
OR b.tag_ID = 2
GROUP BY b.ID
HAVING c = 2
) AS filtered
)
So, first things first, this does work; I wonder, however, if I'm missing some stupidly easy way to simplify this query . . . or should I accept this and move on?
SQL Fiddle here
I had attempted many different types of joins with no success. If only one filter would ever be selected, and simple LEFT JOIN would be perfect. I run into issues when I need to handle more than one filter selection.
Solution 1 using subquery:
SELECT a.genus, a.botanical
FROM a
WHERE a.ID IN (
SELECT b.ID
FROM b
WHERE b.tag_ID = 1
OR b.tag_ID = 2
GROUP BY b.ID
HAVING COUNT(*) = 2
)
Solution 2 using INNER JOIN:
SELECT a.genus, a.botanical
FROM a INNER JOIN
( SELECT b.ID
FROM b
WHERE b.tag_ID IN (1,2)
GROUP BY b.ID
HAVING COUNT(*) = 2 ) b2
USING(ID)
You can try with cross apply like this,
SELECT a.genus
,a.botanical
FROM a
CROSS APPLY (
SELECT b.ID
,COUNT(*) c
FROM b
WHERE (
b.tag_ID = 1
OR b.tag_ID = 2
)
AND a.ID = b.id
GROUP BY b.ID
HAVING c = 2
) b
Table A
id(UNIQUE) name
1 tomato
2 potato
Table B
id AID buy_date buy_money
6 1 2015-01-01 100
7 1 2015-02-02 200
I want to select all A's record filtered with name, and with the latest buy_date and buy_money like this:
A.id A.name B.buy_date B.buy_money
1 tomato 2015-02-02 200
2 potato NULL NULL
How can I write the SQL script? I have tried:
select A.id, A.name, MAX(B.buy_date)
from A left join B on A.id = B.AID
where A.name like '%to%'
Group by A.id
But this only get the right buy_date, but no buy_money.
http://sqlfiddle.com/#!9/bee19b/1
SELECT A.id, A.name, t.*
FROM A
LEFT JOIN (
SELECT B.*
FROM B
LEFT JOIN B b_
ON b.AID = b_.AID
AND b.buy_date<b_.buy_date
WHERE b_.id IS NULL
) t
ON A.id = t.AID
WHERE A.name LIKE '%to%'
2 basic methods here.
Firstly, if the buy date is unique for an AID then you can get the latest buy_date for each AID using a sub query and join that against the B table to get the rest of the details.
Down side of this is that if there are multiple records for an AID with the same buy_date you will get multiple records back
SELECT A.id, A.name, B.buy_date, B.buy_money
FROM A
LEFT OUTER JOIN
(
SELECT AID, MAX(buy_date) AS max_buy_date
FROM B
GROUP BY AID
) AS sub_B
ON A.id = sub_B.AID
LEFT OUTER JOIN B
ON B.AID = sub_B.AID
AND B.buy_date = sub_B.max_buy_date
WHERE A.name like '%to%'
Second solution is to use GROUP_CONCAT to get all the values back, ordered by buy_date descending, then use SUBSTRING_INDEX to get everything up to the first delimiter. Default delimiter for GROUP_CONCAT is a comma but if you values might contain a comma you can easily change that. Down side of this is that it is forcing a conversion of the date and money fields to strings.
SELECT A.id,
A.name,
SUBSTRING_INDEX(GROUP_CONCAT(B.buy_date ORDER BY B.buy_date DESC), ',', 1),
SUBSTRING_INDEX(GROUP_CONCAT(B.buy_money ORDER BY B.buy_date DESC), ',', 1)
FROM A
LEFT OUTER JOIN B
ON B.AID = A.id
WHERE A.name like '%to%'
GROUP BY A.id, A.name
I am an trainee as a software developer. I have a question: How can I access to multiple tables with select and join?
The name of the main-tables are like:
logs_0215
logs_0315
logs_mmyy -> m = month; y = year
The name of the timestamp-tables are like:
timestamp_0215
timestamp_0315
timestamp_mmyy -> m = month; y = year
My query which works only for one table is like:
SELECT a.id, b.stamp, c.name AS portal, d.name AS company, e.name AS protocol, a.value
FROM logs_0315 AS a
LEFT JOIN timestamp_0315 AS b ON a.time_id = b.id
LEFT JOIN portale AS c ON a.portal_id = c.id
LEFT JOIN companies AS d ON a.comp_id = d.id
LEFT JOIN proocols AS e ON a.prot_id = e.id
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
How can I access to all tables which contains logs_mmyy with its timestamp?
Thank you for your help in advance.
Yours sincerely
t.koelpin
You would have to explicitly identify each table; each table has to be identified by name in a FROM clause. SQL does not support wildcard pattern matching for identifiers (table names, column names, etc.).
Given what you've posted, it looks like you could use a UNION ALL set operator to combine results from multiple SELECT statements as a single query:
SELECT a.id, ...
FROM logs_0315 a
LEFT JOIN timestamp_0315 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
UNION ALL
SELECT a.id, ...
FROM logs_0415 a
LEFT JOIN timestamp_0415 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
UNION ALL
SELECT a.id, ...
FROM logs_0515 a
LEFT JOIN timestamp_0515 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
If you need an ORDER BY on the combined result, you can enclose each SELECT statement in parens. Like this:
( SELECT a.id, ...
FROM logs_0315 a
LEFT JOIN timestamp_0315 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
)
UNION ALL
( SELECT a.id, ...
FROM logs_0415 a
LEFT JOIN timestamp_0415 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
)
UNION ALL
( SELECT a.id, ...
FROM logs_0515 a
LEFT JOIN timestamp_0515 AS b ON a.time_id = b.id
...
WHERE b.stamp BETWEEN '2015-05-01' AND '2015-06-25'
)
ORDER BY ...
In order to make this dynamic, to get all tables of the pattern logs_mmyy, you could query information_schema.tables and get the list of tables, and then use that to dynamically generate a statement as above. This approach requires (at a minimum) two separate SQL statements. It's not possible to achieve this type of result in a single SQL statement.
I have the following MySQL tables (Simplified)
DRIVER (D)
----------
id (PK)
name
RACE (RA)
---------
id (PK)
date
RESULT (RE)
-----------
id (PK)
raceid (FK -> RACE.id)
driverid (FK -> DRIVER.id)
bestRound
averageRound
I want to be able to list all drivers with their numRaces, firstRace, lastRace, bestRound, bestAverageRound and the dates on which their bestRound and bestAverageRound happened. I'm having problems with the last two, the dates for bestRound and bestAverageRound.
This is what I have so far:
SELECT D.name, COUNT(DISTINCT RE.raceid) AS numRaces, min(RA.date) AS firstRace,
max(RA.date) AS lastRace, min(RE.bestRound) AS bestRound,
min(RE.averageRound) AS bestAverageRound
FROM DRIVER D
JOIN RESULT RE ON RE.driverid = D.id
JOIN RACE RA ON RA.id = RE.raceid
GROUP BY D.id
ORDER BY D.name
This is working correctly. But how do I proceed to select the dates from the RACE table on which the bestRound and bestAverageRound occurred? Thanks for your time.
Try this solution:
SELECT
a.*, b.date AS bestRoundDate, c.date AS bestAverageRoundDate
FROM
(
SELECT
d.id,
d.name,
COUNT(DISTINCT re.raceid) AS numRaces,
MIN(ra.date) AS firstRace,
MAX(ra.date) AS lastRace,
MIN(re.bestRound) AS bestRound,
MIN(re.averageRound) AS bestAverageRound
FROM driver d
INNER JOIN result re ON d.id = re.driverid
INNER JOIN race ra ON re.raceid = ra.id
GROUP BY d.id, d.name
) a
INNER JOIN
(
SELECT aa.driverid, aa.bestRound, bb.date
FROM result aa
INNER JOIN race bb ON aa.raceid = bb.id
) b ON a.id = b.driverid AND a.bestRound = b.bestRound
INNER JOIN
(
SELECT aa.driverid, aa.bestAverageRound, bb.date
FROM result aa
INNER JOIN race bb ON aa.raceid = bb.id
) c ON a.id = c.driverid AND a.bestAverageRound = c.bestAverageRound
ORDER BY
a.name
I'm not that into MySQL joins, so maybe you could give me a hand. I've got the following tables:
Table a
Fields ID,name
Table b
Fields aID,cID,ID,found
Table c
Fields ID,name
The result I want to get is the following: I want all the records where b.found = 1. Of these records I don't want a.id or a.name, but I want the number of records that would have been returned if I would have wanted so. So if there are five records that have b.found = 1 and c.id = (for example) 3, then I want a returned value of 5, c.id and c.name.
Someone is able to do this?
Actually this is what I want to get from the database:
A list of all records in table C and a count of records in table B that has found = 1 and b.c_id = c.id
Table: a
Fields: ID, name
Table: b
Fields: aID, cID, found
Table: c
Fields: ID, name
SELECT c.ID, c.name, COUNT(1)
FROM b
JOIN c ON c.ID = b.cID AND b.found=1
GROUP BY c.ID
SELECT c.id, c.name, COUNT(*)
FROM c
INNER JOIN b
ON c.id = b.c_id
AND b.found = 1
GROUP BY c.id, c.name
SELECT COUNT(*), c.id, c.name
FROM a, b, c
WHERE a.id = b.a.id AND c.id = b.a.id AND b.found = 1 AND c.id = idThatIAmSearchingFor
Apologies if I didn't get the syntax exact, but I believe that's the basic structure you want. The COUNT function returns the number of rows found by the query.
Something like:
SELECT count(`c`.*),
`c`.`id`,
`c`.`name`
FROM `b`
JOIN `c`
ON `c`.`id` = `b`.`c_id`
WHERE `b.found` = 1
I think this would provide the required output -
select count(*), b.cID, c.name from b
inner join c on c.id=b.cID and b.found=1
group by b.cID
SELECT COUNT(*) AS Count, c.id, c.name
FROM b join a on a.id = b.a_id
WHERE b.found = 1
GROUP BY c.Id;
COUNT returns count of records in each group from GROUP BY.