Access Union with NULL columns not working - ms-access

I have two select queries I am trying to perform UNION on with NULL as columns. Its working fine for one select query but not for other. Please help
I am calculating SUM of ID 1234 for B&C type and grouping them in final select query on ID and performing union on sum of same ID for FTN type.
This means B&C select query will always have "Case" value and not G. And FTN will have G value and not Case.
Problem with the union query is, its generating correct result for B&C
C but showing NULL for G in FTN select query. How do I fix it?
Here is my query
select [ID],sum([case2018]) as [Case18] , NULL AS [G18] from
(SELECT [ID], [ID Was], SUM([Cases]) AS [Case2018], NULL AS [G2018] FROM TblX
WHERE [Package Type]='B&C' and [Year]=2018 and [ID]= 1234
GROUP BY [ID], [ID Was])
GROUP BY [ID]
union
select [ID], NULL AS [Case18] , sum([G2018]) as [G18] from
(SELECT [ID], [ID Was], SUM([G]) AS G18 ,NULL as [Case2018] FROM TblX
WHERE [Package Type]='FTN' and [Year]=2018 and [ID]= 1234
GROUP BY [ID], [ID Was])
GROUP BY [ID]

The second query can't work, because the inner query does not select a field named [G2018].
I think that this nesting of queries isn't necessary. I guess that you wanted the following:
SELECT [ID], SUM([Cases]) AS [Case18], NULL AS [G18]
FROM TblX
WHERE [Package Type]='B&C' AND [Year]=2018 AND [ID]=1234
GROUP BY [ID]
UNION
SELECT [ID], NULL AS [Case18] , SUM([G]) AS [G18]
FROM TblX
WHERE [Package Type]='FTN' AND [Year]=2018 AND [ID]=1234
GROUP BY [ID]
Well, and having a little closer look, doesn't the following single SELECT produce the desired result?
SELECT [ID], [Package Type], SUM([Cases]) AS [Case18], SUM([G]) AS [G18]
FROM TblX
WHERE [Package Type] In ('B&C', 'FTN') AND [Year]=2018 AND [ID]=1234
GROUP BY [ID], [Package Type]

A site I use is http://www.dpriver.com/pp/sqlformat.htm Free online sql formatting tool, beautify sql code instantly for SQL Server, Oracle, DB2, MySQL, Sybase and Access. This gives me readable SQL.
For analysis I then in excel pasted B&C side-by-side with FTN and spotted the error. Then I rearranged a few items in the FTN and changed the spelling to G2018 for
NULL AS [Case2018],
Sum([g]) AS [G2018]
SELECT [id],
Sum([case2018]) AS [Case18],
NULL AS [G18]
FROM (SELECT [id],
[id was],
Sum([cases]) AS [Case2018],
NULL AS [G2018]
FROM tblx
WHERE [package type] = 'B&C'
AND [year] = 2018
AND [id] = 1234
GROUP BY [id],
[id was])
GROUP BY [id]
UNION
SELECT [id],
NULL AS [Case18],
Sum([g2018]) AS [G18]
FROM (SELECT [id],
[id was],
NULL AS [Case2018],
Sum([g]) AS [G2018]
FROM tblx
WHERE [package type] = 'FTN'
AND [year] = 2018
AND [id] = 1234
GROUP BY [id],
[id was])
GROUP BY [id]

Related

MySQL multipe subqueries result in very slow response

I have two tables contacts and calllist. contacts has multiple columns containing phone numbers. calllist has only one column from_number containing phone numbers. I'm trying to get all phone numbers from the column from_number which do not match the phone numbers in the table calllist.
Here is my working but probably very inefficient and slow SQL query:
SELECT from_number AS phone_number, COUNT(from_number) AS number_of_calls
FROM calllist
WHERE from_number NOT IN (
SELECT businessPhone1
FROM contacts
WHERE businessPhone1 IS NOT NULL
)
AND from_number NOT IN (
SELECT businessPhone2
FROM contacts
WHERE businessPhone2 IS NOT NULL
)
AND from_number NOT IN (
SELECT homePhone1
FROM contacts
WHERE homePhone1 IS NOT NULL
)
AND from_number NOT IN (
SELECT homePhone2
FROM contacts
WHERE homePhone2 IS NOT NULL
)
AND from_number NOT IN (
SELECT mobilePhone
FROM contacts
WHERE mobilePhone IS NOT NULL
)
AND (received_at BETWEEN '$startDate' AND DATE_ADD('$endDate', INTERVAL 1 DAY))
GROUP BY phone_number
ORDER BY number_of_calls DESC
LIMIT 10
How do i rewrite this SQL query to be faster? Any help would be much appreciated.
try this
SELECT from_number AS phone_number, COUNT(from_number) AS number_of_calls
FROM calllist
WHERE from_number NOT IN (
SELECT businessPhone1
FROM contacts
WHERE businessPhone1 IS NOT NULL
UNION
SELECT businessPhone2
FROM contacts
WHERE businessPhone2 IS NOT NULL
UNION
SELECT homePhone1
FROM contacts
WHERE homePhone1 IS NOT NULL
UNION
SELECT homePhone2
FROM contacts
WHERE homePhone2 IS NOT NULL
UNION
SELECT mobilePhone
FROM contacts
WHERE mobilePhone IS NOT NULL
)
AND (received_at BETWEEN '$startDate' AND DATE_ADD('$endDate', INTERVAL 1 DAY))
GROUP BY phone_number
ORDER BY number_of_calls DESC
LIMIT 10
I don't like the schema design. You have multiple columns holding 'identical' data -- namely phone numbers. What if technology advances and you need a 6th phone number??
Instead, have a separate table of phone numbers, with linkage (id) to JOIN back to calllist. That gets rid of all the slow NOT IN ( SELECT... ), avoids a messy UNION ALL, etc.
If you desire, the new table could have a 3rd column that says which type of phone it is.
ENUM('unknown', 'company', 'home', 'mobile')
The simplified query goes something like
SELECT cl.from_number AS phone_number,
COUNT(*) AS number_of_calls
FROM calllist AS cl
LEFT JOIN phonenums AS pn ON cl.id = pn.user_id
WHERE cl.received_at >= '$startDate' AND
AND cl.received_at < '$endDate' + INTERVAL 1 DAY
AND pn.number IS NULL -- not found in phonenums
GROUP BY phone_number
ORDER BY number_of_calls DESC
LIMIT 10

What is '-' in front of a column in mysql mean?

What is the significance of "-" (Last line of the code, before a.emp_no) in the following code? I have been trying to understand but I want sure answers. Please Help!!!!!!!!!!!!!!!!!!
SELECT *
FROM
(SELECT
e.emp_no,
e.first_name,
e.last_name,
NULL AS dept_no,
NULL AS from_date
FROM
employees.employees e
WHERE
last_name = 'Denis'
UNION SELECT
NULL AS emp_no,
NULL AS first_name,
NULL AS last_name,
dm.dept_no,
dm.from_date
FROM
employees.dept_manager dm) as a
ORDER BY -a.emp_no DESC;
if emp_no is a number - then it is asking to order by the negative of the number. you could also say
order by a.emp_no

How can I convert MS SQL T-SQL into Subsequent in MySQL

Here I have a MS SQL query which I would like to convert into MySQL. I don't know how to deal with that.
WITH PartitionData as (
SELECT
TOP 10 PurchaseDate.PurchaseDate AS date,
BatchCode,
ROW_NUMBER() OVER( PARTITION BY PurchaseDate.PurchaseDate ORDER BY ( SELECT NULL ) ) AS RowNumber
FROM tblNutBatches
INNER JOIN PurchaseDate ON PurchaseDate.PurchaseDate BETWEEN tblNutBatches.Introduction_date AND tblNutBatches.expiration_date
WHERE PurchaseDate.PurchaseDate = '2004-05-01'
)
SELECT
date as date,
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]
FROM
(
SELECT
date,
BatchCode,
RowNumber
FROM
PartitionData
)AS DataAfterFilter
PIVOT
(
MAX(BatchCode) FOR RowNumber IN ([1], [2], [3], [4], [5], [6], [7], [8], [9])
) A
OUTPUT IN SQL SERVER
Any idea would be appreciated.
You would typically use conditional aggregation:
SELECT date,
MAX(CASE WHEN rn = 1 THEN BatchCode end) as BatchCode1,
MAX(CASE WHEN rn = 2 THEN BatchCode end) as BatchCode2,
...
MAX(CASE WHEN rn = 10 THEN BatchCode end) as BatchCode10
FROM (
SELECT
pd.PurchaseDate AS date,
BatchCode,
ROW_NUMBER() OVER(PARTITION BY pd.PurchaseDate ORDER BY BatchCode) AS rn
FROM tblNutBatches nb
INNER JOIN PurchaseDate pd ON pd.PurchaseDate BETWEEN nb.Introduction_date AND nb.expiration_date
WHERE pd.PurchaseDate = '2004-05-01'
) t
WHERE rn <= 10
GROUP BY date
Notes:
if you want a consistent results, you need ORDER BY clauses in the subquery and in ROW_NUMBER() - I used BatchCode
do prefix BatchCode with the alias of the table it belongs to
the PARTITION BY clause of ROW_NUMBER() and the outer GROUP BY clause are not necessary strictly speaking, since the subquery is filtering on just one data anyway; I retained them, in case you need to remove the filtering at some point. Accordingly, I moved the top 10 filtering logic form the subquery to the outer query.

Incorrect subtotals & Totals in mysql select

I've managed to separate the negatives & positives in the sql select below and I am trying to get the subtotals & totals as indicated in the table pic belom the third column is what the correct results should be.
Below is sql select I've used but its returning the results in column 2 of the above table and its not correct. How can I get the subtotal & total results in column 3
Thanks & Regards
SELECT * FROM
(SELECT
party AS "Account",
sum(debit-credit) AS "Balance"
FROM `tabGL Entry`
WHERE party_type ="Customer" AND MONTH(posting_date) = MONTH(Now()) -1
GROUP BY party WITH ROLLUP
HAVING sum(debit-credit) < 0
UNION ALL
SELECT
party AS "Account",
sum(debit-credit) AS "Balance"
FROM `tabGL Entry`
WHERE party_type ="Customer" AND MONTH(posting_date) = MONTH(Now()) -1
GROUP BY party WITH ROLLUP
HAVING sum(debit-credit) > 0
) rec
UNION ALL
SELECT NULL AS party, sum(dep) AS Balance
FROM (
SELECT SUM(credit-debit) AS dep
FROM `tabGL Entry`
UNION ALL
SELECT SUM(credit-debit) AS nodep
FROM `tabGL Entry`
) AS recb
GROUP BY party WITH ROLLUP
Use this syntax to prevent GROUP BY from being attached incorrectly:
( SELECT ... GROUP BY ... )
UNION ALL
( SELECT ... GROUP BY ... )
Versus
( SELECT ... )
UNION ALL
( SELECT ... )
GROUP BY ...
Where did the word 'Subtotal' come from? I don't see it in the query.
I suspect the inner WITH ROLLUP is tossed. What happens if you remove them?

Returning Minimum ID in Management Studio

Assume the following:
CREATE TABLE #Testing
(
[id] [int] IDENTITY(1,1) NOT NULL,
[store_id] [varchar](3) NULL,
[sku] [varchar](14) NULL,
[qty] [bigint] NULL,
[http_action] [varchar](20) NULL
)
INSERT INTO #Testing (store_id, sku, qty, http_action)
SELECT '001','123456',1,'POST'
UNION ALL
SELECT '002','123456',1,'POST'
UNION ALL
SELECT '002','123456',1,'DELETE'
UNION ALL
SELECT '001','223456',5,'DELETE'
What’s a single query that you could run to return the minimum [id] for each [http_action]? Something like:
MIN_DELETE MIN_POST
3 1
GO
You can use an aggregate function with a CASE expression to get the min(id) for each http_action:
select
min(case when http_action='DELETE' then id end) Min_Delete,
min(case when http_action='POST' then id end) Min_Post
from #testing;
See SQL Fiddle with Demo.
The above query places the min(id) values into separate columns, if you want them in rows, then you could use:
select min(id) id,
http_action
from #testing
group by http_action;
See SQL Fiddle with Demo
Another way of solving it is to use a simple group by on the http_action. You will get a row for each action though:
select http_action, MIN(id) min_id from #Testing group by http_action
Output:
http_action min_id
DELETE 3
POST 1