How do I specify a default value in a MS Access query? - sql

I have three tables similar to the following:
tblInvoices: Number | Date | Customer
tblInvDetails: Invoice | Quantity | Rate | Description
tblPayments: Invoice | Date | Amount
I have created a query called exInvDetails that adds an Amount column to tblInvDetails:
SELECT tblInvDetails.*, [tblInvDetails.Quantity]*[tblInvDetails.Rate]* AS Amount
FROM tblInvDetails;
I then created a query exInvoices to add Total and Balance columns to tblInvoices:
SELECT tblInvoices.*,
(SELECT Sum(exInvDetails.Amount) FROM exInvDetails WHERE exInvDetails.Invoice = tblInvoices.Number) AS Total,
(SELECT Sum(tblPayments.Amount) FROM tblPayments WHERE tblPayments.Invoice = tblInvoices.Number) AS Payments,
(Total-Payments) AS Balance
FROM tblInvoices;
If there are no corresponding payments in tblPayments, the fields are null instead of 0. Is there a way to force the resulting query to put a 0 in this column?

Use the nz() function, as in nz(colName, 0). This will return colName, unless it is null, in which case it will return the 2nd paramter (in this case, 0).

I think that Default Value likes Field location. For example, My Field is ID that is in tblEmpPCs table, I used a criteria below.
IIf([Forms]![frmSearchByEmp]![cboTurul]="ID",[forms]![frmSearchByEmp]![Ezemshigch],[tblEmpPCs].[ID])
There are False value is Default value of Criteria.
I uploaded a picture of my query criteria. It may help you.

Related

sql query count rows per id to by selecting range between 2 min dates in different columns

temp
|id|received |changed |ur|context|
|33|2019-02-18|2019-11-18|
|33|2019-08-02|2019-09-18|
|33|2019-12-27|2019-12-18|
|18|2019-07-14|2019-10-18|
|50|2019-03-20|2019-05-26|
|50|2019-01-19|2019-06-26|
temp2
|id|min_received |min_changed |
|33|2019-02-18 |2019-09-18 |
|18|2019-04-14 |2019-09-18 |
|50|2019-01-11 |2019-05-25 |
The 'temp' table shows users who received a request for an activity. A user can make multiple requests. Hence the received column has multiple dates showing when the requests was received. The 'changed' table shows when the status was changed. There are also multiple values for it.
There is another temp2 column which shows the min dates for received and changed. Need to count total requests per user between the range of values in temp2
The expected result should look like this :- The third row of id- 33 should not be selected because the received date is after the changed date.
|id|total_requests_sent|
|33|2 |
|18|1 |
|50|2 |
Tried Creating 2 CTE's for both MIN date values and joined with the original one
I may be really over-simplifying your task, but wouldn't something like this work?
select
t.id, count (*) as total_requests_sent
from
temp t
join temp2 t2 on
t.id = t2.id
where
t.received between t2.min_received and t2.min_changed
group by
t.id
I believe the output will match your example on the use case you listed, but with a limited dataset it's hard to be sure.

Updating one column based on the value of another column

I have a table named Vendor, within this table I have a column called AccountTerms which is shows only a value (i.e. 0, 1, 2, 3) and so on. I also have a column that I want to use (ulARAgeing) in order to reflect the meaning of that value, such as:
0: Current
1: 30 Days
2: 60 Days
and so on...
What I need is a script that will look at the value in AccountTerms and will then update ulARAgeing to show the word value shown above. How do I do this?
I am going to try to explain this in a simple manner as much as possible so it's easy to understand :
Let's assume, you have a table Vendor setup something like this:
create table Vendor (AccountTerms int, ulARAgeing varchar(50));
And, then we will insert some sample values for both columns in Vendor table:
insert into Vendor values
(0,'Test'),
(1,'Test1'),
(2,'Test2');
Next, we will write an update statement to update your ulARAgeing column based on the values in AccountTerms column in the same table:
update vendor
set ulARAgeing = (CASE
WHEN AccountTerms = 0
THEN 'Current'
WHEN AccountTerms = 1
THEN '30 Days'
WHEN AccountTerms = 2
THEN '60 Days'
END);
CASE WHEN is similar to using IF..ELSE statement in most other programming languages. So, here we will be updating the existing ulARAgeing value to different string value based on the condition in the case when statement. So, for e.g. if the AccountTerms = 0 then we will update the value for ulARAgeing to `Current' and so forth.
To check if the above statement worked correctly, you just need to run the update statement above and then select from the table again:
select * from Vendor;
Result:
+--------------+-----------------+
| AccountTerms | ulARAgeing |
+--------------+-----------------+
| 0 | Current |
| 1 | 30 Days |
| 2 | 60 Days |
+--------------+-----------------+
SQL Fiddle Demo
Assuming you want a simple script to update, then it would be like this:
update
Vendor
set ulARAgeing = 'Current'
where AccountTerms = 0;
Assuming you want a script where it automatically update the column from a logic of numeric progression. Then it would be like this:
;WITH CTE
AS (select
AccountTerms
,ulARAgeing
,CONCAT((AccountTerms * 30), ' Days') as _ulARAgeing
from
Vendor)
UPDATE CTE
SET ulARAgeing = _ulARAgeing;
If by chance the value of "ulARAgeing" come from another table, then the script using "; WITH", you must use a join to get the correct value, instead of using a logic of progression.

How can I pivot dataset in Google BigQuery?

I have a massive dataset with this schema:
Customer INTEGER
CategoryID INTEGER
CategoryName STRING
ProjectStage INTEGER
NextStepID INTEGER
NextStepName STRING
NextStepIsAnchor BOOLEAN
I heed to get the resulting set where each customer will be only on one row and his/her next steps will be in the columnts like this:
Customer | CategoryID | CategoryName | ProjectStage | NextStep1ID | NextStep1Name | NextStep2ID | NextStep2Name | ... etc.
I tried to play with NTH function of BigQuery but it works only for the first occurrence of the NextStepID:
SELECT
customer,
nth(1, NextStepID)
FROM [2015_05.customers_wunique_nextsteps]
group by customer
but when I try to add more columns:
SELECT
customer,
nth(1, NextStepID),
nth(2, NextStepID)
FROM [2015_05.customers_wunique_nextsteps]
group by customer
I get this error:
Error: Function 'NTH(2, [NextStepID])' cannot be used in a distributed
query, this function can only be correctly computed for queries that
run on a single node.
Any ideas?
Now I "pivot" the results with Excel and small VBA script, but when datasets grow bigger calculation time exceeds all limits...
Thanks in advance! :)
Function NTH is applicable to REPEATED fields, where it chooses the nth repeating element (the error message can be improved). So first step would be to build REPEATED field out of NextStepID, and it can be done with NEST aggregation function. Then you can use NTH as scoped aggregation function:
SELECT
Customer,
NTH(1, NextStepID) WITHIN RECORD AS NextStepID1,
NTH(2, NextStepID) WITHIN RECORD AS NextStepID2,
NTH(3, NextStepID) WITHIN RECORD AS NextStepID3
FROM (
SELECT Customer, NEST(NextStepID) AS NextStepID
FROM [2015_05.customers_wunique_nextsteps] GROUP BY Customer)

Adding a percent column to MS Access Query

I'm trying to add a column which calculates percentages of different products in MS Access Query. Basically, this is the structure of the query that I'm trying to reach:
Product |
Total |
Percentage
Prod1 |
15 |
21.13%
Prod2 |
23 |
32.39%
Prod3 |
33 |
46.48%
Product |
71 |
100%
The formula for finding the percent I use is: ([Total Q of a Product]/[Totals of all Products])*100, but when I try to use the expression builder (since my SQL skills are basic) in MS Access to calculate it..
= [CountOfProcuts] / Sum([CountOfProducts])
..I receive an error message "Cannot have aggregate function in GROUP BY clause.. (and the expression goes here)". I also tried the option with two queries: one that calculates only the totals and another that use the first one to calculate the percentages, but the result was the same.
I'll be grateful if someone can help me with this.
You can get all but the last row of your desired output with this query.
SELECT
y.Product,
y.Total,
Format((y.Total/sub.SumOfTotal),'#.##%') AS Percentage
FROM
YourTable AS y,
(
SELECT Sum(Total) AS SumOfTotal
FROM YourTable
) AS sub;
Since that query does not include a JOIN or WHERE condition, it returns a cross join between the table and the single row of the subquery.
If you need the last row from your question example, you can UNION the query with another which returns the fabricated row you want. In this example, I used a custom Dual table which is designed to always contain one and only one row. But you could substitute another table or query which returns a single row.
SELECT
y.Product,
y.Total,
Format((y.Total/sub.SumOfTotal),'#.##%') AS Percentage
FROM
YourTable AS y,
(
SELECT Sum(Total) AS SumOfTotal
FROM YourTable
) AS sub
UNION ALL
SELECT
'Product',
DSum('Total', 'YourTable'),
'100%'
FROM Dual;

Modifying column value according to status, and adding extra rows. (sql)

In my table I have a "name" column and a "status" column.
the status is either true or false.
And another table contains a number which is a total amount.
The result that I want to get is a table with two columns:
name | status
and and example of a data:
a | available
a | available
a | not available
a | not available
a | available
when "a" is in the name column and the availability is the status column.
The total amount from the second table indicates the total number of "a" rows that i need to have, and the status depends on the true/false from the status column in the original table.
If the status is "true" I need to write "available" and when "false" then "not available".
If the total amount value is bigger than the data I have in the first table, I need to add rows according to the total amount with the status "available".
For example, If I have 3 records of "a", when one has the status "true" and the other two have the status "false", and the total amount is 4, In the result I need to get 4 rows with the name "a", 2 of them "available" and 2 "not available" (the given 3 rows, plus one row to make it 4).
My question is, how can I change the value according to the data in the table? (Write available/ not available)
And how can I add a certain amount of rows with preset values (same name as before, and "available" status)?
"...how can I change the value according to the data in the table?"
You can use CASE() to test for the value of the column.
SELECT name,
CASE WHEN status = 'true'
THEN 'available'
ELSE 'not available'
END status
FROM tableName
For future answer-seekers:
To get the 'fake' rows, one way is to use are recursive CTE:
WITH Expanded_Data as (SELECT Counted_Data.name,
CAST('true' as VARCHAR(5)) as status,
Counted_Data.count + 1 as count,
Total.count as limit
FROM (SELECT name, COUNT(*) as count
FROM Data
GROUP BY name) Counted_Data
JOIN Total
ON Counted_Data.name = Total.name
AND Counted_Data.count < Total.count
UNION ALL
SELECT name, status, count + 1, limit
FROM Expanded_Data
WHERE count < limit)
SELECT name, CASE WHEN status = 'true'
THEN 'available'
ELSE 'not available' END
FROM (SELECT name, status
FROM Data
UNION ALL
SELECT name, status
FROM Expanded_Data) d;
(have a working SQL Fiddle example.)
I'm a little worried about the initial duplication in the source data though; I can only hope there is more 'unique' information as well.