Convert SQL query to work in MS Access SQL - sql

I'm trying to convert SQL query to work in MS-Access, is there any suggested way? thank you
SELECT
colldet.college,
COUNT(DISTINCT manuscript.p_name) AS A,
COUNT(DISTINCT CASE WHEN s_p = 'منجز' THEN p_name END) AS B,
COUNT(DISTINCT CASE WHEN s_p = 'منجز منشور' THEN p_name END) AS C,
COUNT(DISTINCT CASE WHEN s_p = 'مخطط' THEN p_name END) AS D
FROM manuscript
RIGHT OUTER JOIN colldet
ON manuscript.coll_name = colldet.college
GROUP BY colldet.college

As June7 notes, Access doesn't support COUNT DISTINCT so you'll need to make things distinct before counting. Also as June7 suggests use Iif() instead of CASE. This is a guess:
SELECT Q.College,
COUNT(Q.A1) AS A,
COUNT(Q.B1) AS B,
COUNT(Q.C1) AS C,
COUNT(Q.D1) AS D
FROM (SELECT DISTINCT colldet.college,
manuscript.p_name AS A1,
IIF(s_p = 'منجز',p_name,Null) AS B1,
IIF(s_p = 'منجز منشور',p_name,Null) AS C1,
IIF(s_p = 'مخطط',p_name,Null) AS D1
FROM manuscript
RIGHT OUTER JOIN colldet
ON manuscript.coll_name = colldet.college)
AS Q
GROUP BY Q.college

Related

How to simplify SQL code for "MAX" operator

I was trying to solve one task and found the solution, it works, but the code is "awful" and duplicates itself, may be someone can just help me with that?
SELECT b."N",b."ID",max(b.summ) as "jjj", b.country
FROM(SELECT großhandelsfirma.name as "N",großhandelsfirma.steuerid as "ID",
sum(verkauft.anzahl) as "summ", großhandelsfirma.land as "country"
FROM großhandelsfirma
INNER JOIN verkauft on großhandelsfirma.name = verkauft.ghname
GROUP BY großhandelsfirma.name,großhandelsfirma.steuerid,großhandelsfirma.land) b
WHERE b.summ in (SELECT max(b.summ)
FROM(SELECT großhandelsfirma.name as "N",großhandelsfirma.steuerid as "ID",
sum(verkauft.anzahl) as "summ", großhandelsfirma.land as "country"
FROM großhandelsfirma
INNER JOIN verkauft on großhandelsfirma.name = verkauft.ghname
GROUP BY großhandelsfirma.name,großhandelsfirma.steuerid,großhandelsfirma.land) b
GROUP BY b.country)
GROUP BY b."N",b."ID", b.country
Original code was ok, but gave me solution with not needed lines, the main task was to find company with highest "sum" in each country, but I got some duplicates with countries, so answer included 2-3 best "summs" in 1 country, but I needed only 1.
This was the old code:
SELECT großhandelsfirma.name as N, großhandelsfirma.steuerid as ID,
sum verkauft.anzahl as summ, großhandelsfirm.land as country
FROM großhandelsfirma
INNER JOIN verkauft on großhandelsfirma.name = verkauft.ghname
GROUP BY großhandelsfirma.name, großhandelsfirma.steuerid, großhandelsfirma.land
Perhaps the window function ROW_NUMBER has been implemented in your RDBMS.
It can be used to calculate a number based on an order.
So it'll be 1 for the top 1.
SELECT N, ID, country, summ
FROM
(
SELECT f.name as N, f.steuerid as ID, f.land as country
, SUM(v.anzahl) as summ
, ROW_NUMBER() OVER (PARTITION BY f.land ORDER BY SUM(v.anzahl) DESC) as RN
FROM großhandelsfirma f
JOIN verkauft v ON f.name = v.ghname
GROUP BY f.name, f.steuerid, f.land
) q
WHERE RN = 1
Did you try doing the same with CTE? Please have a look into below link.
CTE
Or else use the TOP 1 from the result filtered.

How to replace SELECTS in an Aggregate Function SUM()

How do I create a workaround for a SELECT statement in a SUM-Function
I am currently migrating my Sybase Database towards MsSQL.
One of my Views has some SUMs in its main select statements which then use subSelects for a case in my SUM function
SELECT
SUM(CASE WHEN e.s = 'E'
AND EXISTS
( SELECT
1
FROM
system.E
JOIN system.EF
ON EF.EID = E.ID
WHERE
E.CID = C.ID
AND EF.T='smth')
AND A.AC= 'smthelse'
AND ET.EC not in( 'lol','lul','lel')
THEN
B.A
ELSE
0.0
END) AS smth
FROM ...
I expect it to SUM the b.A when the Select statement has at least 1 result
but instead I get this error message:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
I think it doesnt allow me to use a subSelect in the SUM-function, but im not sure how to fix it.
You can replace the subquery with a lateral JOIN by using the OUTER APPLY operator:
SELECT . . .
SUM(CASE WHEN e.s = 'E' AND
eef.ID IS NOT NULL AND
A.AC = 'smthelse' AND
ET.EC NOT IN ( 'lol', 'lul', 'lel')
THEN B.A ELSE 0.0
END) AS smth
FROM ... OUTER APPLY
(SELECT TOP (1) E.*
FROM system.E JOIN
system.EF
ON EF.EID = E.ID
WHERE E.CID = C.ID AND EF.T = 'smth'
) EEF

Only one expression can be specified in the select list when the subquery is not introduced with EXISTS. 3

I am trying to execute 2 SELECT queries.
I have the following:
SELECT DISTINCT
A.USERNUMBER, B.USERNAME
(SELECT
B.USERNUMBER, COUNT(1)
FROM B
INNER JOIN A ON B.USERNUMBER = A.USERNUMBER
WHERE
A.USERNUMBER = B.USERNUMBER
AND B.PBALANCE <> '0'
OR B.IBALANCE <> '0'
OR B.SCBALANCE <> '0'
GROUP BY B.USERNUMBER)
FROM
A
INNER JOIN
B ON A.USERNUMBER = B.USERNUMBER
WHERE
A.USERNUMBER = B.USERNUMBER
Thanks in advance.
When you have
SELECT a,b,..,(SELECT ... ), g, h,....
the second 'SELECT' in parens, the subquery, is contributing one column to your result, just like a, 'b', etc. Therefore it can have only one column it its select clause.

Selecting ONLY Duplicates from a joined tables query

I have the following query that I'm trying to join two tables matching their ID so I can get the duplicated values in "c.code". I've tried a lot of queries but nothing works. I have a 500k rows in my database and with this query I only get 5k back, which is not right. Im positive it's at least 200K. I also tried to use Excel but it's too much for it to handle.
Any ideas?
Thanks in advance, everyone.
SELECT c.code, c.name as SCT_Name, t.name as SYNONYM_Name, count(c.code)
FROM database.Terms as t
join database.dbo.Concepts as c on c.ConceptId = t.ConceptId
where t.TermTypeCode = 'SYNONYM' and t.ConceptTypeCode = 'NAME_Code' and c.retired = '0'
Group by c.code, c.name, t.name
HAVING COUNT(c.code) > = 1
Order by c.code
with data as (
select c.code, c.name as SCT_Name, t.name as SYNONYM_Name
from database.Terms as t inner join database.dbo.Concepts as c
on c.ConceptId = t.ConceptId
where
t.TermTypeCode = 'SYNONYM'
and t.ConceptTypeCode = 'NAME_Code'
and c.retired = '0'
)
select *
--, (select count(*) from data as d2 where d2.code = data.code) as code_count
--, count(*) over (partition by code) as code_count
from data
where code in (select code from data group by code having count(*) > 1)
order by code
If you want just duplicates of c.code, your Group By is wrong (and so is your Having clause). Try this:
SELECT c.code
FROM database.Terms as t
join database.dbo.Concepts as c on c.ConceptId = t.ConceptId
where t.TermTypeCode = 'SYNONYM' and t.ConceptTypeCode = 'NAME_Code' and c.retired = '0'
Group by c.code
HAVING COUNT(c.code) > 1
This will return all rows where you have more than one c.code value.
You need to use INTERSECT instead of JOIN. Basically you perform the select on the first table then intersect with the second table. The result is the duplicate rows.
Only select the id column, though, otherwise the intersect won't work as expected.

Oracle SQL division

I have
SELECT
COUNT(*) AS a,
SUM(CASE WHEN r.hn IS NOT NULL THEN 1 ELSE 0 END) AS b,
SUM(CASE WHEN r.hn IS NULL THEN 1 ELSE 0 END) AS c,
( ____ / ____ ) AS d
FROM
x
LEFT JOIN (SELECT DISTINCT xn FROM yn) r ON x.xn = y.xn;
I need the blanks on line 4 to be the values set to 'a' and 'c', I'm not sure what the correct syntax is though.
You can't refer to column aliases in the same level of the query (except in the order by clause), so you have to either repeat the original expression as in #juergend's answer, or use an inline view:
SELECT a, b, c, a/c AS d
FROM (
SELECT
COUNT(*) AS a,
SUM(CASE WHEN y.hn IS NOT NULL THEN 1 ELSE 0 END) AS b,
SUM(CASE WHEN y.hn IS NULL THEN 1 ELSE 0 END) AS c
FROM x
LEFT JOIN (SELECT DISTINCT xn FROM yn) y ON y.xn = x.xn
);
For complicated expressions this is a bit simpler and easier to maintain - if the expression changes you only have to modify it in one place, reducing the risk of a mistake.
If you're trying to make d the ratio of nulls to the total then you just need the division reversed, as c/a; and if you wanted the percentage then100*c/a, possibly rounded or truncated to a certain precision.
And as Clockwork-Muse mentioned, since count() ignores nulls, you coudl use that instead of the two sum() calls:
SELECT a, b, c, a/c AS d
FROM (
SELECT
COUNT(*) AS a,
COUNT(y.hn) AS b,
COUNT(*) - COUNT(y.hn) AS c
FROM x
LEFT JOIN (SELECT DISTINCT xn FROM yn) y ON y.xn = x.xn
);
... or you could calculate c in the outer query too, as (b - a), though that makes the d calculation messier.
The correct syntax is to rewrite the statements again. You can't re-use alias names in the select clause.
SELECT COUNT(*) AS t,
count(r.hn) AS c,
SUM(case when r.hn IS NULL then 1 end) AS u,
count(r.hn) / SUM(case when r.hn IS NULL then 1 end) AS p
FROM h
LEFT JOIN (SELECT DISTINCT hn FROM r) r ON h.hn = r.hn;