I'm working in Access 365 for this project. I have a query:
SELECT inv_no, SalesID FROM GetOpenItems WHERE cust_id = '28017'
Which returns:
inv_no
SalesID
55414
30
I have another query:
SELECT SalesID FROM GetSalesStaff WHERE TRIM(SalesManager)=GetUserName()
Which returns:
SalesID
30
Yet when I combine the two:
SELECT inv_no, SalesID FROM GetOpenItems WHERE cust_id = '28017' AND SalesID IN (SELECT SalesID FROM GetSalesStaff WHERE TRIM(SalesManager)=GetUserName())
I get an empty set.
I've used VarType() in test queries to determine that SalesID is vbString in GetOpenItems and vbString in GetSalesStaff, so they are both the same type.
I've tried adding the table names in the query as follows:
SELECT inv_no, SalesID FROM GetOpenItems WHERE cust_id = '28017' AND GetOpenItems.SalesID IN (SELECT GetSalesStaff.SalesID FROM GetSalesStaff WHERE TRIM(SalesManager)=GetUserName())
I've also tried converting SalesID on both sides of the 'IN' by wrapping in CLng(), same result. If I only wrap one or the other I get the expected type mismatch error, which supports that they are the same type currently.
I cannot for the life of me figure out why it's visually the same value yet somehow not evaluating the IN properly, and it's probably going to be something I'm staring at and glossing over. Any thoughts?
ADDENDUM:
Here is the GetUserName() function (which is really just a get method for a global var):
Public Function GetUserName() As String
GetUserName = UserName
End Function
The portion that sets the global var is inside another big function that is called on applicaton load:
UserName = Environ("USERNAME")
But I'm currently manually using Username = "mmoses" for testing.
That the query using this code returns 30 when run stand-alone makes me believe it should be evaluating to "IN (30)" in the larger query as well, so I don't suspect an issue in this bit...
ADDENDUM 2:
In response to questions in comments:
The immediate window shows 'mmoses' when the query fails and that Debug.Print is run, which is as expected.
mmoses is tied in the GetSalesStaff query to SalesID 30 (which is what SELECT SalesID FROM GetSalesStaff WHERE TRIM(SalesManager)=GetUserName() returns).
Additionally, I know it works with SalesID as text/number, but it's not an issue of a global variable losing value because I can immediately run the debug above and it returns the correct global value, and the query used inside the IN () bit runs on its own fine consistently
To test this I also rewrote all global vars to be TempVars and the same result is found.
The issue seems isolated to the odd quirk that:
SELECT SalesID FROM GetSalesStaff WHERE TRIM(SalesManager)=GetUserName()
Returns a single value, 30.
SELECT inv_no, SalesID FROM GetOpenItems WHERE cust_id = '28017' AND SalesID IN (30)
Returns the proper results, yet:
SELECT inv_no, SalesID FROM GetOpenItems WHERE cust_id = '28017' AND SalesID IN (SELECT SalesID FROM GetSalesStaff WHERE TRIM(SalesManager)=GetUserName())
returns nothing, even when all 3 queries are run back to back (and rerunning the previous queries still continues to return the proper results).
Related
My Current Database
I would like to add a field that classifies each student by whether or not they failed a course. For example, if they failed a class the new field might have them marked as 'x'. If a student did not fail any course they may be marked as 'y'. How do I do this? Thanks.
Calculate in query using nested query or domain aggregate function:
SELECT *, IIf(SELECT Count(*) FROM tablename AS Q1 WHERE Q1.PassOrFail = "Fail" AND Q1.Student_ID=tablename.StudentID)=0, "Y", "X") AS Cat
FROM tablename;
or
SELECT *, IIf(DCount("*", "tablename", "PassOrFail = 'Fail' AND Student_ID=" & [Student_ID])=0, "Y", "X") AS Cat
FROM tablename;
Domain aggregate functions can cause slow performance in large dataset.
I have a table, links that links two categories (parent & child) together. The table has five fields:
autoinc
parent_category_name year(4) NOT NULL
parent_category_year varchar(255) NOT NULL
child_category_name year(4) NOT NULL
child_category_year varchar(255) NOT NULL
I am trying to write an INSERT SELECT that grabs both the parent & child category_id, and inserts it into a temp table.
INSERT INTO temp (parent_category_id, child_category_id)
SELECT parent.parent_category_id, child.child_category_id
FROM links
JOIN categories AS parent
ON parent.name = link.parent_category_name
AND parent.year = link.parent_category_year
JOIN categories AS child
ON child.name = link.child_category_name
AND child.year = link.child_category_year
This query works fine, but I need to apply some business rules. The rules are:
The parent year must be the same as the child year
OR
The parent year must be one year less than the child year
I've added a WHERE clause to my query:
WHERE link.child_category_year = link.parent_category_year
OR link.child_category_year - link.parent_category_year = 1
When this INSERT statement executes in my Perl code, I get the following exception:
DBI Exception: DBD::mysql::db do failed: BIGINT UNSIGNED value is out of range in '(`my_database`.`links`.`child_category_year` - `my_database`.`links`.`parent_category_year`)' [for Statement "
So, I take it that the INSERT does not like my date subtraction in the WHERE clause. I explored using the DATEDIFF function, but I am not simply looking for a one year difference in dates, but rather one year less on the parent than the child.
How can I accomplish this without the insert error?
OR link.child_category_year - link.parent_category_year = 1 may produce negative substraction result. Of course negative value cannot be stored as UNSIGNED.
Simply convert your expression to
OR link.child_category_year = link.parent_category_year + 1
Totally unclear why "year" would be stored as an unsigned bigint. That is way overkill for my understanding of "year".
In any case, why not rephrase the logic to:
WHERE link.parent_category_year = link.child_category_year
link.parent_category_year = link.child_category_year + 1
In general, you should not have a problem adding 1 to an unsigned value.
This is my first time knowing that there's a YEAR datatype and after reading the official documentation I understand that:
MySQL displays YEAR values in YYYY format, with a range of 1901 to 2155, and 0000.
Although, it doesn't specifically said that the type is UNSIGNED but the last line in the documentation says:
If strict SQL mode is not enabled, MySQL converts invalid YEAR values to 0000. In strict SQL mode, attempting to insert an invalid YEAR value produces an error.
That means you received the error because one (or more) of the subtracted value in the condition of OR link.child_category_year - link.parent_category_year = 1 is returning negative.
Now, there are a few options you could try:
You can use CAST function and change the year data as SIGNED like :
WHERE link.child_category_year = link.parent_category_year
OR CAST(link.child_category_year AS SIGNED) - CAST(link.parent_category_year AS SIGNED) = 1
Or you can set NO_UNSIGNED_SUBTRACTION sql_mode and run the query as is:
SET sql_mode='NO_UNSIGNED_SUBTRACTION'
You can also consider changing the YEAR datatype to INTEGER and run the query as is:
ALTER TABLE links
MODIFY parent_category_year INT NOT NULL,
MODIFY child_category_year INT NOT NULL;
I've been charged with finding how many telecasts does each series have?
I have the following tables from which to choose from:
So far I've gotten the following:
sql <- "select series_name, sum(telecast_id) from telecast group by
series_name limit 10"
res <- dbSendQuery(con, sql)
df_tc <- dbFetch(res)
print(df_tc)
It returns too many values though.
Any suggestions?
sum returns the total of the values in the brackets. So you're adding up the telecast IDs and getting large values. To determine "how many", as in "how many records", you need to use count(). If you assume that no record has a NULL telecast ID, then leave the column name blank inside the brackets. I've also named the result ("As n") but that's optional. And why limit the top 10? That was not specified in the question, so delete it.
sql <- "Select series_name, count() As n from telecast group by series_name"
The other commands seem ok.
So my query is the following, which may return many results:
SELECT P_CODE, NAME FROM TEST.dbo.PEOPLE
WHERE NAME LIKE '%JA%'
AND P_CODE LIKE '%003%'
AND DOB LIKE '%1958%'
AND HKID = ''
AND (MOBILE LIKE '%28%' OR TEL LIKE '%28%')
I would like to integrate this into a Stored Procedure (or View?) so that it will only return a result if the query results in exactly 1 row. If there's 0 or > 1, then it should return no results.
If you just want to return an empty resultset in cases other than 1:
;WITH x AS
(
SELECT P_CODE, NAME, c = COUNT(*) OVER()
FROM TEST.dbo.PEOPLE
WHERE NAME LIKE '%JA%'
AND P_CODE LIKE '%003%'
AND DOB LIKE '%1958%'
AND HKID = ''
AND (MOBILE LIKE '%28%' OR TEL LIKE '%28%')
)
SELECT P_CODE, NAME FROM x WHERE c = 1;
Otherwise, you'll have to run the query twice (or dump the results to intermediate storage, such as a #temp table) - once to get the count, and once to decide based on the count whether to run the SELECT or not.
Effectively you want something akin to FirstOrDefault() from the Linq-to-SQL implementation but done on the server-side which means you will need to execute the query in a stored procedure, dumping the results into a temp table variable and then access ##ROWCOUNT afterwards to get the number of rows that were returned and then decide whether or not to forward the results on to the caller. If you do, be sure to use TOP 1 in the query from the temp table so that you only get a single result out as you desire.
UPDATE:
I described the alternate solution from what Aaron describes in his answer (which I like better).
Removed unnecessary TOP specifier in solution specification.
I am trying to Sum() the column Status where Status = 'operational'. I am having trouble figuring out how to sum the actual word "operational".
I have tried multiple different variations of the statement below (the one I posted is the most basic form) but I get the error: data type varchar is invalid for sum operator.
Can anybody help?
SELECT SUM(status) As 'TotalOperationalSTIDevices'
FROM netinfo_device_details
WHERE LoopBackAddress LIKE '10.12%' AND Status = 'Operational'
Try
Select COUNT(*) As 'TotalOperationalSTIDevices' from netinfo_device_details where LoopBackAddress Like '10.12%' and Status = 'Operational'
You need to use COUNT:
SELECT COUNT(*) As TotalOperationalSTIDevices
FROM netinfo_device_details
WHERE LoopBackAddress LIKE '10.12%' AND Status = 'Operational';
The SUM aggregation function really does a SUM of a set of numbers. COUNT just counts the number of rows.
Since the actual content of the row is not relevant, you can use COUNT(*) instead of COUNT(status) if you want.