Crystal Report: SQL Subquery Issue with 'null' Results - sql-server

When I run the following SQL query in SMS, I correctly get "null" values in the second document_desc column (from patient_documents_1). This shows me that the patient documents that exist for a certain patient do not include the required bh_pharm document. Perfect!
SELECT
patients.last_name, patients.first_name,
patient_documents.document_description,
patient_documents_1.document_description
FROM patients
INNER JOIN patient_documents ON patients.pat_id = patient_documents.pat_id
LEFT OUTER JOIN (
select patient_documents.pat_id, patient_documents.document_description
from patient_documents where patient_documents.document_description = 'bh_pharm' )
as patient_documents_1 ON patients.pat_id = patient_documents_1.pat_id
WHERE
( patient_documents.timestamp >= {ts '2015-02-01 00:00:00'} AND patient_documents.timestamp < {ts '2015-03-01 00:00:00'} ) AND
patient_documents_1.document_description is null
How can I do this in a Crystal Report?
Everything I try results in an empty report. Either that or I have to include every record and every document description. I only want the report to show me what patients are missing the "bh_pharm" document. Can Crystal Reports handle 'null' results from a subquery or subreport?
Thanks in advance ...

Open the crystal report then there instead of selecting the tables select command and copy the same query there.
Now go design and generate the report.

Does it work without the LEFT JOIN to the subquery? Ie do you get results after taking out that join and all references to patient_documents_1?
If not, then make sure you are configuring crystal reports to query the SQL Server correctly.
Edit:
Does this work? It might be the curly braces but I also did some gratuitous rewriting...
WITH patient_documents_1 as
(
select patient_documents.pat_id
from patient_documents
where patient_documents.document_description = 'bh_pharm'
group by patient_documents.pat_id
),
noBH as (
SELECT
patients.last_name,
patients.first_name,
patients.pat_id
FROM patients
LEFT OUTER JOIN patient_documents_1 on patients.pat_id = patient_documents_1.pat_id
WHERE
patient_documents_1.document_description is null
)
Select
noBH.*,
patient_documents.document_description
from noBH
INNER JOIN patient_documents ON noBH.pat_id = patient_documents.pat_id
WHERE
patient_documents.timestamp between '2015-02-01' and '2015-02-28'
Oh yeah, are there patients who don't have the bh_pharm document but do have timestamps in feb 2015?

Start with a new report.
The only table you need to add to your report is the patients table. (If you alias it then make sure to change it in the query below.)
Add a SQL Expression to return the count. It will evaluate to zero when no documents with the right description are found. Copy everything below including the parentheses. Call it something like DocumentCount.
(
select count(*)
from patient_documents as pd
where
pd.document_description = 'bh_pharm'
and pd.pat_id = patients.pat_id /* alias on "patients" must match */
)
Add a filter to the record select formula to limit it to the ones you want to display.
{%DocumentCount} = 0

Related

SQL Server - select a commonly named column over multiple joined tables where the last edit date is most recent

Our County recently purchased a new real-estate system. I have created a view that joins over a dozen tables. (assessment, taxpayer, collections, etc...)
Every table has a last change data and last change user field.
We would like to know when a parcel number was last changed in the system and what login made those changes.
I was able to pull the most recent change data by using the following nested query...
SELECT
... ,
(SELECT MAX(v)
FROM (VALUES (table1.last_chg_datetime), (table2.last_chg_datetime),
(table3.last_chg_datetime), (table4.last_chg_datetime), ... ,
(tableN.last_chg_datetime)) AS value(v)) AS last_chg_datetime
FROM table1
LEFT OUTER JOIN table2 ...
What is the best way to also pull the last changed user from the table that corresponds with the last changed date?
I am sure this could be done with a stored procedure. I was just wondering if this could also be extracted by altering the nested query?
We are running SQL Server 2016.
The query could be rewritten as:
SELECT ... ,sub. *
FROM table1
LEFT OUTER JOIN table2 ...
OUTER APPLY (SELECT TOP 1 *
FROM (VALUES (table1.last_chg_datetime, table1.user), (table2.last_chg_datetime, table2.user),
(table3.last_chg_datetime, table3.user), (table4.last_chg_datetime, table4.user), ... ,
(tableN.last_chg_datetime, tableN.user)) AS value(v, user_name)
ORDER BY v DESC
) sub;
It could be also extended by table name:
(VALUES ('table1', table1.last_chg_datetime, table1.user),
('table2', table2.last_chg_datetime, table2.user), ...
) AS value(table_name, v, user_name)

How to get column value of join query in SSRS?

I have select join query for generating report in SSRS. Query is working fine in SQL Server but as I add same query as dataset in SSRS and try to get rows count using CountRows() function it always return 0 (Zero). I'm not getting where my query is going wrong.
SQL Query
SELECT PR.NAME
FROm innovator.PROJECT PR
INNER JOIN innovator.PROJECT_RISK LPR ON LPR.SOURCE_ID = Pr.ID
INNER JOIN innovator.RISK_MANAGEMENT LR ON LR.id = LPR.RELATED_ID
Inner join innovator.PROGRAM_PROJECT P ON PR.ID = P.RELATED_ID
Inner Join innovator.PROGRAM PP ON P.SOURCE_ID = PP.ID
WHERE pp.ID = #Id
Fetching total count using CountRows() for Textbox
=CountRows(Fields!NAME.Value, "DataSetRisk")
DataSetRisk is Dataset name and Name is column name of Project Table
Use the CountRows function. For example
=CountRows("MyDataset")
Example : =CountRows("DataSetRisk")
will give you the number of rows in MyDataSet.
Try something a little simpler: Count(Fields!NAME.Value) as a column. This assumes, of course, that field name actually is populated. If the column is in separate groups, it will provide a count for each group, otherwise it will count for the entire report.

Need query to determine number of attachments for each issue

I have a database in SQL Server that has three tables: Issues, Attachments, and Requestors. I need a single query that returns all the columns contained in the "Issues" and "Attachments" tables. Listed below is the query that I've created, but it's not working as expected:
SELECT A.*,
B.*,
SubQuery.attachmentcount
FROM [DB].[dbo].[issues] AS A
FULL OUTER JOIN [DB].[dbo].[requestors] AS B
ON A.issue_id = B.issue_id,
(SELECT Count(attachments.attachment_id) AS AttachmentCount
FROM issues
LEFT OUTER JOIN attachments
ON issues.issue_id = attachments.issue_id
WHERE attachments.attachment_status = 1
GROUP BY issues.issue_id) AS SubQuery;
Pictures describing the three tables are listed below:
Any ideas on how to fix my query?
Thanks,
"I need a single query that returns all the columns contained in the "Issues" and "Attachments" tables".
Based on this sentence try this:
SELECT A.Issue_ID, I.Issue_Name,r.Name, COUNT(A.attachment_id) AS Count
FROM Attachments as A
INNER JOIN Issues I on I.issue_id = A.issue_id
INNER JOIN requestors as R on A.issue_id = R.requestor_id
WHERE A.attachment_status = 1
GROUP BY A.Issue_ID, I.Issue_Name, r.Name
--Specify all columns by name (don't use *)
Keep It Simple and Try This!
SELECT i.Issue_ID, i.Issue_Name, COUNT(a.attachment_id) AS AttachmentCount
FROM attachments a JOIN
issues i ON
i.issue_id = a.issue_id
WHERE a.attachment_status = 1
GROUP BY i.Issue_ID, i.Issue_Name
Add your Desired Columns in Both Select List and Group By Clause and you are done.

Filtering Query with NOT EXISTS

I am currently attempting to query a database using SQL Server in Visual Studio. The database in question contains payment information, primarily identifying transactions and their resulting software licenses via OrderID and License ID. Ocassionally, these licenses get revoked due to misuse.
Right now, I'm attempting to run a query that returns all customers based upon this:
Select
[Order].LastName,
[Order].FirstName,
[Order].CompanyOrganization,
[Order].EmailAddress,
[Order].Country,
[License].LicenseID,
[License].InstanceCount
From [Order], [License]
Where
[License].OrderID = [Order].OrderID
AND [Order].Status = 1
AND not exists (Select LicenseID From [LicenseRevocation])
Order by [License].InstanceCount DESC;
The query returns no results, and I know it's because of the "NOT EXISTS" portion. However, I'm not sure why. Can somebody clear up how "EXISTS" works and how to implement it into my query?
The exists() function is true if the query inside it would produce at least one record, thus not exists() is only true if the query inside it would produce zero records.
In your case you are querying the entire LicenseRevocation inside not exists(), so your query would only return anything if that table was completely empty.
You would use a condition in the query to look for a specific record in it, something like this:
not exists (Select * From [LicenseRevocation] Where LicenseID = [License].LicenceID)
That will make the query return the records where there is no corresponding record in the LicenseRevocation table.
You need to define a condition on which you check for values if there exist or not,
Also use ON clause syntax for your joins.
Select [Order].LastName
, [Order].FirstName
, [Order].CompanyOrganization
, [Order].EmailAddress
, [Order].Country
, [License].LicenseID
, [License].InstanceCount
From [Order]
INNER JOIN [License] ON [License].OrderID = [Order].OrderID
Where [Order].[Status] = 1
AND NOT EXISTS (Select 1
From [LicenseRevocation]
WHERE LicenseID = [License].LicenseID) --<-- you are missing this condition
Order by [License].InstanceCount DESC;
this solution uses NOT IN and proper JOIN syntax but should give you the result you want
SELECT [Order].LastName, [Order].FirstName, [Order].CompanyOrganization,
[Order].EmailAddress, [Order].Country,
[License].LicenseID, [License].InstanceCount
FROM [Order]
INNER JOIN [License] ON [License].OrderID = [Order].OrderID
WHERE [Order].Status = 1
AND [License].LicenseID NOT IN (
SELECT LicenseID
FROM [LicenseRevocation] )
ORDER BY [License].InstanceCount DESC;
ps. use table ALIAS
First of all, write your query using proper JOINS, and use a standard LEFT OUTER JOIN:
Select
[Order].LastName,
[Order].FirstName,
[Order].CompanyOrganization,
[Order].EmailAddress,
[Order].Country,
[License].LicenseID,
[License].InstanceCount
From [Order]
INNER JOIN [License] ON [License].OrderID = [Order].OrderID
LEFT OUTER JOIN [LicenseRevocation] ON [License].LicenseID = [LicenseRevocation].LicenseID
Where [Order].Status = 1
AND [LicenseRevocation].LicenseID IS NULL
Order by [License].InstanceCount DESC;

Is it possible to perform a join in Access on a second column if the first is blank?

I have this ugly source data with two columns, let's call them EmpID and SomeCode. Generally EmpID maps to the EmployeeListing table. But sometimes, people are entering the Employee IDs in the SomeCode field.
The person previously running this report in Excel 'solved' this problem by performing multiple vlookups with if statements, as well as running some manual checks to ensure results were accurate. As I'm moving these files to Access I am not sure how best to handle this scenario.
Ideally, I'm hoping to tell my queries to do a Left Join on SomeCode if EmpID is null, otherwise Left Join on EmpID
Unfortunately, there's no way for me to force validation or anything of the sort in the source data.
Here's the full SQL query I'm working on:
SELECT DDATransMaster.Fulfillment,
DDATransMaster.ConfirmationNumber,
DDATransMaster.PromotionCode,
DDATransMaster.DirectSellerNumber,
NZ([DDATransMaster]![DirectSellerNumber],[DDATransMaster]![PromotionCode]) AS EmpJoin,
EmployeeLookup.ID AS EmpLookup,
FROM FROM DDATransMaster
LEFT JOIN EmployeeLookup ON NZ([DDATransMaster]![DirectSellerNumber],[DDATransMaster]![PromotionCode]) = EmployeeLookup.[Employee #])
You can create a query like this:
SELECT
IIf(EmpID Is Null, SomeCode, EmpID) AS join_field,
field2,
etc
FROM YourTable
Or if the query will always be used within an Access session, Nz is more concise.
SELECT
Nz(EmpID, SomeCode) AS join_field,
field2,
etc
FROM YourTable
When you join that query to your other table, the Access query designer can represent the join between join_field and some matching field in the other table. If you were to attempt the IIf or Nz as part of the join's ON clause, the query designer can't display the join correctly in Design View --- it could still work, but may not be as convenient if you're new to Access SQL.
See whether this SQL gives you what you want.
SELECT
dda.Fulfillment,
dda.ConfirmationNumber,
dda.PromotionCode,
dda.DirectSellerNumber,
NZ(dda.DirectSellerNumber,dda.PromotionCode) AS EmpJoin,
el.ID AS EmpLookup
FROM
DDATransMaster AS dda
LEFT JOIN EmployeeLookup AS el
ON NZ(dda.DirectSellerNumber,dda.PromotionCode) = el.[Employee #])
But I would use the Nz part in a subquery.
SELECT
sub.Fulfillment,
sub.ConfirmationNumber,
sub.PromotionCode,
sub.DirectSellerNumber,
sub.EmpJoin,
el.ID AS EmpLookup
FROM
(
SELECT
Fulfillment,
ConfirmationNumber,
PromotionCode,
DirectSellerNumber,
NZ(DirectSellerNumber,PromotionCode) AS EmpJoin
FROM DDATransMaster
) AS sub
LEFT JOIN EmployeeLookup AS el
ON sub.EmpJoin = el.[Employee #])
What about:
LEFT JOIN EmployeeListing ON NZ(EmpID, SomeCode)
as your join, nz() uses the second parameter if the first is null, I'm not 100% sure this sort of join works in access. Worth 20 seconds to try though.
Hope it works.
You Could use a Union:
SELECT DDATransMaster.Fulfillment,
DDATransMaster.ConfirmationNumber,
DDATransMaster.PromotionCode,
DDATransMaster.DirectSellerNumber,
EmployeeLookup.ID AS EmpLookup
FROM DDATransMaster
LEFT JOIN EmployeeLookup ON
DDATransMaster.DirectSellerNumber = EmployeeLookup.[Employee #]
where DDATransMaster.DirectSellerNumber IS NOT NULL
Union
SELECT DDATransMaster.Fulfillment,
DDATransMaster.ConfirmationNumber,
DDATransMaster.PromotionCode,
DDATransMaster.DirectSellerNumber,
EmployeeLookup.ID AS EmpLookup
FROM DDATransMaster
LEFT JOIN EmployeeLookup ON
DDATransMaster.PromotionCode = EmployeeLookup.[Employee #]
where DDATransMaster.DirectSellerNumber IS NULL;

Resources