Can I use a report paramater as a section of the WHERE clause - sql

I have a query that runs great as is like this
WHERE (customer IN (#cust))
and #cust is a customer or a multiple list of customers
what I want to add is an AND with more in another optional parameter like
No: #expiring = " "
OR
Yes: #expiring = " AND getDate() >= dateAdd(d,[expiryWarning],[expiryDate]) "
then I want to add that to the end of the WHERE and have it do that second part if it's chosen from the dropdown as Yes or No so I can show the whole list of customers or just the ones expiring in the report.
WHERE (customer IN (#cust)) #expiring
but I am seeing an error when I try to run this report
that there's an error near #expiring
any insight? I've been searching all day, is this even possible?

You need to change your where clause to take #expiring into account like this.
WHERE customer in (#cust)
AND (#expiring='No' OR getDate() >= dateAdd(d,[expiryWarning],[expiryDate]))
So if #expring is 'No' then that part of the WHERE clause always returns true. If expiring = 'Yes' then the date criteria must be true else that part will return false.

Related

Access Query parameter that uses a separate table to eliminate or include records

I have one table, Main, which is the main accounting table with all the transactions. I have a second table, Payments, which i keep track of payments and specifically which invoice a given payment has paid off.
I need a report that will be dynamic and flexible; really my accounting workhorse. The report i need will search between dates, customer Id's, record status, account1, account2, and pay status.
So i have a form built out to handle these inputs, but i am having trouble with "pay status" as in, how to form a parameter with it. My current code,
SELECT Main.Invo, Main.InvoDate, Main.Amt, Main.PartyId, Main.TboInvoRloc, Main.TboDocNo, Main.TboPax
FROM Main
WHERE Main.RecSrce<>"Accounts"
AND Main.InvoDate BETWEEN [Forms]![GeneralReport]![startDate] AND [Forms]![GeneralReport]![endDate]
AND Main.PartyId =IIF([Forms]![GeneralReport]![PartyID] IS NULL, PartyID, [Forms]![GeneralReport]![PartyID])
AND Main.Status = IIF([Forms]![GeneralReport]![Status] IS NULL, Status, [Forms]![GeneralReport]![Status])
AND Main.Ac1 = IIF([Forms]![GeneralReport]![Ac1] IS NULL, Ac1, [Forms]![GeneralReport]![Ac1])
AND Main.Ac2 = IIF([Forms]![GeneralReport]![Ac2] IS NULL, Ac2, [Forms]![GeneralReport]![Ac2])
;
covers everything but the "pay status." I wanted to do something like
If checkbox=true, then include paid items, else exclude items where Main.Invo = Payments.DueInvo
My other thought was to exclude the paid items in the initial query, and then include them in a subsequent union query if the checkbox is checked. Any help or thoughts would be appreciated.
Set unbound checkbox for TripleState Yes. Or use a combobox with 3 options (Paid, Unpaid, All) because users might be confused by a triple state checkbox.
Build an aggregate query on Payments table that totals the payments by invoice. Join that query to Main (this assumes invoice is unique in Main).
Calculate a field and set a parameter under that field.
If using checkbox:
IsNotPaid: Amt <> Nz(SumOfPayments,0)
LIKE Forms![GeneralReport]!checkboxname & "*"
If using combobox:
PaidStatus: IIf(Amt = Nz(SumOfPayments,0), "Paid", "Unpaid")
LIKE IIf(Forms![GeneralReport]!comboboxname = "All", "*", Forms![GeneralReport]!comboboxname)
An alternative to aggregate query is DSum() domain aggregate function but that will probably perform slower.
Consider setting payment detail columns to NULL depending on checkbox. Specifically, join the Payments table and run a logical condition on fields in SELECT assigning NULL or not.
SELECT m.Invo, m.InvoDate, m.Amt,
m.PartyId, m.TboInvoRloc,
m.TboDocNo, m.TboPax,
IIF(Forms]![GeneralReport]![myCheckBox] = True,
p.PaymentDetailColumn1, NULL) AS PayColumn1,
IIF(Forms]![GeneralReport]![myCheckBox] = True,
p.PaymentDetailColumn2, NULL) AS PayColumn2,
IIF(Forms]![GeneralReport]![myCheckBox] = True,
p.PaymentDetailColumne, NULL) AS PayColumn3
...
FROM Main m
LEFT JOIN Payments p ON m.Invo = p.DueInvo
WHERE m.RecSrce <> 'Accounts'
AND m.InvoDate BETWEEN [Forms]![GeneralReport]![startDate]
AND [Forms]![GeneralReport]![endDate]
AND m.PartyId = NZ([Forms]![GeneralReport]![PartyID], m.PartyID)
AND m.Status = NZ([Forms]![GeneralReport]![Status], m.Status)
AND m.Ac1 = NZ([Forms]![GeneralReport]![Ac1], m.Ac1)
AND m.Ac2 = NZ([Forms]![GeneralReport]![Ac2], m.Ac2);
If you want dynamic columns (i.e., payment details) to appear or not depending on condition, this cannot come directly from SQL but some connecting app layer code (VBA, Python, etc.) to building dynamic queries. Recall SQL is a declarative language and once identifiers are assigned they are immutable. However, if using reports, you do want all columns explicitly defined from recordsource query.

Multiple entries in crystal reportviewer after adding a SQL expression field

I am using Visual Studio 2017 and I installed the latest crystal reportviewer (22)
What I want is to click a button and create a report from the customer that is selected in the datagridview and the addresses that are shown in the second datagridview.
I managed to do all that but the problem is that a few fields contain numbers which need to be converted to text. An SQL query I would use to do this would be like:
SELECT c.customer_nr, c.status, s.rename FROM CUSTOMERS c INNER JOIN SETUP s on s.id = c.status WHERE s.afk = 'STA'
In my SETUP database I have the columns ID,AFK and RENAME so if the status would be 1 it would convert to text: "ACTIVE", if status = 2 it would convert to "INACTIVE" for example.
I could do something with a formula field like this:
IF ({c.status} = 1) THEN "ACTIVE" ELSE
IF ({c.status}) = 2 THEN "INACTIVE"
but that is not good because i could add another status or change the name in the database etc.
So then I tried with an SQL expression field and I put something like this:
(
SELECT "SETUP"."RENAME" FROM SETUP
WHERE "SETUP"."AFK" = 'STA' AND "SETUP"."ID" = "CUSTOMERS"."STATUS"
)
There must be something wrong because I get the correct conversion but there is only one address in the database but I get 7 pages all with the same address. There should only be one address like I get when I remove the SQL expression field. Where does it go wrong?
* EDIT *
I found the problem. When I create a new database that contains only unique id's then it works. In my original database I have multiple times the id's 1,2,3,4,5 but with different abbreviations in column AFK. Somehow the query looks for the id value and every time it finds this id no matter the AFK value it generates an entry for the address value.
Maybe in the future I will find out how this exactly works for now I have a workaround.
Create a new table for example CrRepSta and add the following entries:
ID,AFK,RENAME
1,STA,Active
2,STA,Inactive
etc
The new query:
(
SELECT "CrRepSta"."RENAME" FROM CrRepSta
WHERE "CrRepSta"."AFK" = 'STA' AND "CrRepSta"."ID" = "CUSTOMERS"."STATUS"
)
And by the way the statement "CrRepSta"."AFK" = 'STA' is not really needed.

using criteria in an update query involving a join

I'm using MS Access
The SQL below updates the CurrNumTees field in the Parent tblContact records with the number of tblTorTee records that have an end date (which is not the ultimate effect I am aiming for, but I provide it as a starting point.
UPDATE tblContact
INNER JOIN tblTorTee ON tblContact.ContactId = tblTorTee.TorId
SET tblContact!CurNumTees = DCount("[tblTorTee.EndDate]",
"tbltortee","Torid = " & [ContactId]);
I need to update the CurrNumTees field with the number of records in tblTorTee that do not have an EndDate, in other words, that field is blank. I’ve tried using WHERE and HAVING and IS NULL in various combinations and locations, but without success. Could you help point me in the right direction?
The MS Access COUNT function does not count nulls, so I think you have to do this in two stages.
Firstly create a query like this:
SELECT TorId, IIF(ISNULL(EndDate),1,0) AS isN
FROM tblTorTee
WHERE EndDate IS NULL;
And save it as QryEndDateNull
Now you can run an Update Query like this:
UPDATE tblContact
SET tblContact.CurNumTees = DSUM("IsN","QryEndDateNull","TorId = " & [ContactID]);
Saving calculated data (data dependent on other data) is usually a bad design, especially aggregate data. Should just calculate when needed.
Did you try the IS NULL criteria within the DCount()?
UPDATE tblContact Set CurNumTees = DCount("*", "tblTorTee", "EndDate Is Null AND TorId = " & [ContactId]);

Crystal Report - Suppressing formula based on two conditions

I am new to crystal report & i stuck in a condition which is not executing due to improper coding. so please help me to resolve this.
Thanks in advance.
Here in my report I wanted to display the sales person name but there are 2 categories in sales person i.e Product & Vertical.
P-XXX-James Koren
V-YYY-BBB-Aditi N
Here I just wanted to pick the sales person name in both categories & for that I used mid function as : Mid({Salesperson Name},11,155) this is for vertical sales person, and for product sales person i used mid function as Mid({Salesperson Name},7,155) both are working fine.
but I wanted to suppress the vertical sales person name if the sales order belongs to product person & vice versa
I tried If condition but its not working properly please insist me for how to combine the 2 formulas & suppress one formula if 2 formulas are evaluated.
you can use if condition on suppress like
If
({your field} = "P" and //product or you can use the query here to find P
PageNumber > 1)
then false //don't Supress
else true //Supress
you can use the same formula on other field's suppress like
If
({your field} = "V" and //Vertical or you can use the query here to find V
PageNumber > 1)
then false //don't Supress
else true //Supress

If-else for null condition SQL

I am going to create a livereport using three example inputs:
Document Start Date
Document End Date
Emp ID
These are 3 rows in the SQL table DocumentData.
What I want to reproduce is the following:
If the user does not put any value in "Emp ID" field, it should show all "Document Start Date" and "Document End Date". Otherwise, only values corresponding to that "Emp ID" should be shown.
It may be very simple but I still need the query.
Use an OR and pass the value to the query twice.
In generic query code (not knowing how livelink makes calls)
SELECT * FROM DOCUMENT
WHERE CREATED_DATE BETWEEN $startDate AND $endDate
AND (EMP_ID = $empId OR $empId IS NULL)
Perhaps this could be a solution:
-- should work perfectly
select *
from DocumentData
where
case
when :emp_id is null then 1 -- attention :emp_id introduced in stead of emp_id
when emp_id = :emp_id then 1
else 0
end = 1
The :emp_id should be the variable that comes from the application (the field that is being altered by the user). The 1 in the case when statement acts as a true condition.