SQL code in Access says error in FROM clause - sql

SELECT
p.Name,
p.Age,
MAX(COUNT(m.winTeam_ID) / (COUNT(m.winTeam_ID) + COUNT(m.lossTeam_ID)))
FROM Players AS p
INNER JOIN Teams AS t
ON t.ID = p.Team_ID
INNER JOIN Matches AS m
ON m.Team_ID = t.ID
GROUP BY
p.Name,
p.Age;

I can suggest the following query:
SELECT TOP 1
p.Name,
p.Age,
COUNT(m.winTeam_ID) / (COUNT(m.winTeam_ID) + COUNT(m.lossTeam_ID))
FROM (Players AS p
INNER JOIN Teams AS t
ON t.ID = p.Team_ID)
INNER JOIN Matches AS m
ON m.Team_ID = t.ID
GROUP BY
p.Name,
p.Age
ORDER BY
COUNT(m.winTeam_ID) / (COUNT(m.winTeam_ID) + COUNT(m.lossTeam_ID)) DESC;
This fixes the syntax problem with your joins. It also interprets the MAX as meaning that you want the record with the maximum ratio of counts. In this case, we can use TOP 1 along with ORDER BY to identify this max record.

MS Access requires strange parentheses when you have more than one join. In addition, MAX(COUNT(m.winTeam_ID)) doesn't make sense. I don't know what you are trying to calculate in the SELECT. Perhaps this does what you want:
SELECT p.Name, p.Age,
COUNT(m.winTeam_ID) / (COUNT(m.winTeam_ID) + COUNT(m.lossTeam_ID)))
FROM (Players AS p INNER JOIN
Teams AS t
ON t.ID = p.Team_ID
) INNER JOIN
Matches AS m
ON m.Team_ID = t.ID
GROUP BY p.Name, p.Age;

I think your Matches table shouldn't have a Team_ID And instead you have winTeam_ID and lossTeam_ID!
And also you want to query players of a team with - something like - the best win-rate.
If so, Use a query like this - tested on SQL Server only -:
select
p.Age, p.Name, ts.rate
from
Players p
join
(select top(1) -- sub-query will return just first record
t.ID
, sum(case when (t.ID = winTeam_ID) then 1 else 0 end) as wins
, sum(case when (t.ID = lossTeam_ID) then 1 else 0 end) as losses
, sum(case when (t.ID = winTeam_ID) then 1.0 else 0.0 end) /
(sum(case when (t.ID = winTeam_ID) then 1.0 else 0.0 end) + sum(case when (t.ID = lossTeam_ID) then 1.0 else 0.0 end)) as rate
from Teams as t
left join Matches as m
on t.ID = m.winTeam_ID
or t.ID = lossTeam_ID
group by t.ID
order by rate desc -- This will make max rate as first
) as ts -- Team stats calculated in this sub-query
on p.Team_ID = ts.ID;

Related

Count with several conditions - oracle sql

Im trying to do a count of particular transactions that have specific conditions and cant seem to make it work.Also in the query I select other columns from other tables
for example:
Want to select all transactions
where transactions.ID_1 = transactions.ID_2,
where transaction.dir = "outbound" and transactions.status in ("completed", "processing")
and do a count on this. like:
select
m.ID
,m.Number
,t.Status
,(column that counts of all transactions with the conditions mentioned above)
,p.label
from module m
inner join transactions t on t.ID_1 = m.ID
inner join process p on p.ID = m.ID`
Tried with sum and when and if statement but doesn't work
I consider this is a simple count you can use the next script:
SELECT COUNT(transactions.ID_1)
FROM YOUR_TABLE
WHERE transactions.ID_1 = transactions.ID_2
AND transaction.dir = "xxx"
AND transactions.status in ("a", "b")
Seems like you want to GROUP BY. Use a CASEexpression to do conditional aggregation.
select
m.ID
,m.Number
,t.Status
,SUM(case when transaction.dir = 'outbound'
and transactions.status in ('completed', 'processing') then 1
else 0
end)
,p.label
from module m
inner join transactions t on t.ID_1 = m.ID
inner join process p on p.ID = m.ID
group by m.ID
,m.Number
,t.Status
p.label

CTE TABLE WITH ORDER BY ERROR MESSAGE SQL SERVER

;WITH myTree AS
(
SELECT
y.User_id, y.user_usercode, y.user_username,
y.user_uplineID,
trans_WinLose, y.User_ID AS sourceID, trans_id,
trans_Rolling, y.User_Level,
lvl1.User_Level AS Level_lvl1, lvl2.User_Level AS Level_lvl2,
y.User_GivenPT, lvl1.User_GivenPT AS GivenPT_lvl1,
lvl2.User_GivenPT AS GivenPT_lvl2, y.User_GivenComm,
lvl1.User_GivenComm AS downline_Comm
FROM
tbl_user y
INNER JOIN
tbl_trans x ON x.trans_Robot_ID = y.User_RobotID
INNER JOIN
tbl_user lvl1 ON y.user_uplineID = lvl1.User_ID
INNER JOIN
tbl_user lvl2 ON lvl1.user_uplineID = lvl2.User_ID
UNION ALL
SELECT
u.User_ID, u.user_usercode, u.user_username, u.user_uplineID,
t.trans_WinLose, t.sourceID AS sourceID, t.trans_Id,
t.trans_Rolling, u.User_Level, t.User_Level, t.Level_lvl1,
u.User_GivenPT, t.User_GivenPT, t.GivenPT_lvl1,
u.User_GivenComm, t.User_GivenComm
FROM
myTree t
INNER JOIN
tbl_user u ON t.user_uplineID = u.User_ID
)
SELECT *
FROM
(SELECT
mytree.*,
(SELECT
CASE
WHEN Level_lvl1 = 7 THEN GivenPT_lvl1
WHEN level_lvl2 = 7 THEN User_GivenPT-GivenPT_Lvl2
ELSE (CASE
WHEN (User_GivenPT-GivenPT_lvl1) > 0
THEN User_GivenPT - GivenPT_lvl1
ELSE 0
END)
END) AS Net_PT
FROM
Mytree
ORDER BY
mytree.trans_ID) AS c
I would like to order by mytree.trans_ID, but I get an error:
Msg 1033, Level 15, State 1, Line 17
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
How to solve this problem?
Another possibility is to remove the outer query when querying the CTE - it doesn't seem to serve any purpose.
;with myTree as (
select y.User_id,y.user_usercode,y.user_username,y.user_uplineID,trans_WinLose, y.User_ID as sourceID, trans_id,trans_Rolling,y.User_Level,lvl1.User_Level as Level_lvl1,lvl2.User_Level as Level_lvl2,y.User_GivenPT,lvl1.User_GivenPT as GivenPT_lvl1 ,lvl2.User_GivenPT as GivenPT_lvl2,y.User_GivenComm,lvl1.User_GivenComm as downline_Comm from tbl_user y
Inner join tbl_trans x on x.trans_Robot_ID = y.User_RobotID
Inner join tbl_user lvl1 on y.user_uplineID = lvl1.User_ID
Inner join tbl_user lvl2 on lvl1.user_uplineID = lvl2.User_ID
union all
select u.User_ID,u.user_usercode,u.user_username,u.user_uplineID,t.trans_WinLose, t.sourceID as sourceID, t.trans_Id,t.trans_Rolling,u.User_Level,t.User_Level,t.Level_lvl1,u.User_GivenPT,t.User_GivenPT,t.GivenPT_lvl1,u.User_GivenComm,t.User_GivenComm
from myTree t
inner join tbl_user u on t.user_uplineID = u.User_ID
)
SELECT mytree.*,
(SELECT CASE
WHEN Level_lvl1=7 THEN GivenPT_lvl1
WHEN level_lvl2=7 THEN User_GivenPT-GivenPT_Lvl2
ELSE (CASE WHEN (User_GivenPT-GivenPT_lvl1) > 0 THEN User_GivenPT-GivenPT_lvl1 else 0 END)
END) as Net_PT
From Mytree order by mytree.trans_ID
SQL behaves with data in Mathematics Sets manner. In Sets the order of data and elements are meaningless. So when you are dealing with CTE, sub-queries, views, inline table value functions etc, that are used to return a set of data, you are not allowed to order and sort them.
You need to sort data when you need to show them in output or you are using TOP or OFFSET-Fetch or etc commands, where the Order By helps these commands to work as they should be.
You should rewrite your query as:
;with myTree as (
select y.User_id,y.user_usercode,y.user_username,y.user_uplineID,trans_WinLose, y.User_ID as sourceID, trans_id,trans_Rolling,y.User_Level,lvl1.User_Level as Level_lvl1,lvl2.User_Level as Level_lvl2,y.User_GivenPT,lvl1.User_GivenPT as GivenPT_lvl1 ,lvl2.User_GivenPT as GivenPT_lvl2,y.User_GivenComm,lvl1.User_GivenComm as downline_Comm from tbl_user y
Inner join tbl_trans x on x.trans_Robot_ID = y.User_RobotID
Inner join tbl_user lvl1 on y.user_uplineID = lvl1.User_ID
Inner join tbl_user lvl2 on lvl1.user_uplineID = lvl2.User_ID
union all
select u.User_ID,u.user_usercode,u.user_username,u.user_uplineID,t.trans_WinLose, t.sourceID as sourceID, t.trans_Id,t.trans_Rolling,u.User_Level,t.User_Level,t.Level_lvl1,u.User_GivenPT,t.User_GivenPT,t.GivenPT_lvl1,u.User_GivenComm,t.User_GivenComm
from myTree t
inner join tbl_user u on t.user_uplineID = u.User_ID
)select * from (SELECT mytree.*,
(SELECT CASE
WHEN Level_lvl1=7 THEN GivenPT_lvl1
WHEN level_lvl2=7 THEN User_GivenPT-GivenPT_Lvl2
ELSE (CASE WHEN (User_GivenPT-GivenPT_lvl1) > 0 THEN User_GivenPT-GivenPT_lvl1 else 0 END)
END) as Net_PT
From Mytree) as c
order by c.trans_ID
From Mytree order by mytree.trans_ID OFFSET 0 ROWS
change it to this, solved

How to optimize SQL Server query

I am copying data from one table to another table. While copying I am doing some calculation to modify one column.
SQL Server query:
INSERT INTO rat_proj_duration_map_2
SELECT
r.*,
r.hour_val / (CASE
WHEN week_val = 1 AND
(SELECT TOP 1
hrswk
FROM UserProfileRATinterface_view us
INNER JOIN users u
ON u.username = us.username
WHERE calwk = 2
AND r.uid = u.uid
AND yr = 2016)
> 0 THEN (SELECT TOP 1
hrswk
FROM UserProfileRATinterface_view us
INNER JOIN users u
ON u.username = us.username
WHERE calwk = 2
AND r.uid = u.uid
AND yr = 2016)
WHEN (SELECT
hrswk
FROM UserProfileRATinterface_view us
INNER JOIN users u
ON u.username = us.username
WHERE r.week_val = us.calwk
AND r.uid = u.uid
AND yr = 2016)
< 1 AND
(SELECT
MAX(hrswk)
FROM UserProfileRATinterface_view us
INNER JOIN users u
ON u.username = us.username
WHERE r.uid = u.uid
AND yr = 2016)
> 0 THEN (SELECT
MAX(hrswk)
FROM UserProfileRATinterface_view us
INNER JOIN users u
ON u.username = us.username
WHERE r.uid = u.uid
AND yr = 2016)
WHEN (SELECT
COUNT(*)
FROM UserProfileRATinterface_view us
INNER JOIN users u
ON u.username = us.username
WHERE r.uid = u.uid
AND yr = 2016)
<= 0 THEN 1
ELSE (SELECT
hrswk
FROM UserProfileRATinterface_view us
INNER JOIN users u
ON u.username = us.username
WHERE r.week_val = us.calwk
AND r.uid = u.uid
AND yr = 2016)
END) * 100 AS percentage_val
FROM rat_proj_duration_map r
When I run this query I getting time out issue.
TCP Provider: Timeout error [258]
SQL Server is not in my hand to increase time out value.
Is it possible to optimize my SQL query?
Are you sure this query is logically correct? You have several TOP 1s without specific ORDER BY, scalar comparison of subselect without TOP (which, I assume, may return more than one row if you are using top in other subselects with same source).
And yes - this query can be optimized. You can obtain all the values you need with a single subselect statement and avoid multiple execution of same subselects for each row of rat_proj_duration_map which you are having now:
INSERT INTO rat_proj_duration_map_2
SELECT
r.*,
r.hour_val / (CASE
WHEN week_val = 1 AND us.min_hrswk_2 > 0
THEN us.min_hrswk_2
WHEN us.min_hrswk_week_val <1
AND max_hrswk > 0
THEN max_hrswk
WHEN us.cnt <= 0
THEN 1
ELSE min_hrswk_week_val
END) * 100 as percentage_val
FROM
rat_proj_duration_map r
OUTER APPLY
(
SELECT
count(*) as cnt,
MIN(CASE WHEN calcw = 2 THEN hrswk END) as min_hrswk_2,
MIN(CASE WHEN calcw = r.week_val THEN hrswk END) as min_hrswk_week_val,
MAX(hrswk) as max_hrswk
FROM UserProfileRATinterface_view us
inner join users u on u.username=us.username
WHERE r.uid=u.uid and yr=2016
) us
But I can't be sure if original logic is correct. And the idea of that case to me looks like this:
...
r.hour_val / COALESCE(NULLIF(us.min_hrswk_2, 0),
NULLIF(us.min_hrswk_week_val, 0), NULLIF(max_hrswk, 0), 1)
...
The subqueries in your case clause seem to be essentially the same. You could simplify the whole command by defining a grouped version (... where yr=2016 group by u.uid) of this subquery (preferrably as a common table expression) and then work with that. This could potentially save a lot of redundant operations.
The following might work (have not tested it):
;WITH usrall as (
SELECT u.uid ui, hrswk hw, r.week wk, us.calwk cw
FROM UserProfileRATinterface_view us
INNER JOIN users u on u.username=us.username
WHERE r.uid=u.uid and yr=2016
), usrgrp as (
SELECT ui gui, MAX(hrswk) ghw, count(*) gcnt FROM usrall group by ui
), denom as (
SELECT gui dui, COALESCE( MAX(w2.hw), MAX(wkwc.hw), MAX(gwh) ) dnm
FROM usrgrp
LEFT JOIN usrall w2 ON w2.ui=gui AND w2.cw=2 AND w2.hw>0
LEFT JOIN usrall wkcw ON wkcw.ui=gui AND wkcw.wk=wkcw.cw AND wkwc.hw<1
GROUP BY gui
)
SELECT r.*, r.hour_val / d.dnm
FROM rat_proj_duration_map r
INNER JOIN denom d ON d.dui=u.uid
Essentially I have tried (I hope it works :-/) to replace the case construct by a COALESCE() function that checks the three possible calculated values one after the other. The first non-null value is accepted.
As I said: I have not tested it. Good luck

Displaying two or more sets of aggregate function on a single table

I am trying to display the results of many count functions distinguished by different where criteria side by side.
select *
from
(SELECT a.location, count(b.description)
from locations.a left join status b on a.zone =b.zone
where b.date_issued = #1/3/2012#
group by a.location) X
inner join
(SELECT a.location, count(b.description)
from locations.a left join status b on a.zone =b.zone
where b.date_issued = #1/2/2012#
group by a.location) Y
on X.zone = Y.zone;
i cannot refer to X and Y in the main select as MS access keeps asking me for a parameter value and if i use Select * i get error in the the from cluase
please help
You want to use conditional aggregation. From the use of # for the date constant, I am guessing that you are using Access:
SELECT a.location,
sum(iif(b.date_issued = #1/3/2012#, 1, 0) as val_20130103,
sum(iif(b.date_issued = #1/2/2012#, 1, 0) as val_20130102
from locations.a left join
status b
on a.zone =b.zone
group by a.location;
The generic SQL would use case:
SELECT a.location,
sum(case when b.date_issued = #1/3/2012# then 1 else 0 end) as val_20130103,
sum(case when b.date_issued = #1/2/2012# then 1 else 0 end) as val_20130102
from locations.a left join
status b
on a.zone =b.zone
group by a.location
Try this?
select *
from
(SELECT a.location, count(b.description) as Count, a.Zone
from locations a
left join status b on a.zone =b.zone
where b.date_issued = #1/3/2012#
group by a.location) X
inner join
(SELECT a.location, count(b.description) as Count, a.Zone
from locations a
left join status b on a.zone =b.zone
where b.date_issued = #1/2/2012#
group by a.location) Y
on X.zone = Y.zone;

SQL LEFT JOIN combined with regular joins

I have the following query that joins a bunch of tables.
I'd like to get every record from the INDUSTRY table that has consolidated_industry_id = 1 regardless of whether or not it matches the other tables. I believe this needs to be done with a LEFT JOIN?
SELECT attr.industry_id AS option_id,
attr.industry AS option_name,
uj.ft_job_industry_id,
Avg(CASE
WHEN s.salary > 0 THEN s.salary
END) AS average,
Count(CASE
WHEN s.salary > 0 THEN attr.industry
END) AS count_non_zero,
Count(attr.industry_id) AS count_total
FROM industry attr,
user_job_ft_job uj,
salary_ft_job s,
user_job_ft_job ut,
[user] u,
user_education_mba_school mba
WHERE u.user_id = uj.user_id
AND u.user_id = ut.user_id
AND u.user_id = mba.user_id
AND uj.ft_job_industry_id = attr.industry_id
AND uj.user_job_ft_job_id = s.user_job_id
AND u.include_in_student_site_results = 1
AND u.site_instance_id IN ( 1 )
AND uj.job_type_id = 1
AND attr.consolidated_industry_id = 1
AND mba.mba_graduation_year_id NOT IN ( 8, 9 )
AND uj.admin_approved = 1
GROUP BY attr.industry_id,
attr.industry,
uj.ft_job_industry_id
This returns only one row, but there are 8 matches in the industry table where consolidated_industry_id = 1.
--- EDIT: The real question here is, how do I combine the LEFT JOIN with the regular joins?
Use left join for tables that may miss a corresponding record. Put the conditions for each table in the on clause of the join, not in the where, as that would in effect make them inner joins anyway. Something like:
select
attr.industry_id AS option_id, attr.industry AS option_name,
uj.ft_job_industry_id, AVG(CASE WHEN s.salary > 0 THEN s.salary END) AS average,
COUNT(CASE WHEN s.salary > 0 THEN attr.industry END) as count_non_zero,
COUNT(attr.industry_id) as count_total
from
industry attr
left join user_job_ft_job uj on uj.ft_job_industry_id = attr.industry_id and uj.job_type_id = 1 and uj.admin_approved = 1
left join salary_ft_job s on uj.user_job_ft_job_id = s.user_job_id
left join [user] u on u.user_id = uj.user_id and u.include_in_student_site_results = 1 and u.site_instance_id IN (1)
left join user_job_ft_job ut on u.user_id = ut.user_id
left join user_education_mba_school mba on u.user_id = mba.user_id and mba.mba_graduation_year_id not in (8, 9)
where
attr.consolidated_industry_id = 1
group by
attr.industry_id, attr.industry, uj.ft_job_industry_id
If you have any tables that you know always have a corresponding record, just use innser join for that.