I have that error with execute "The multi-part identifier "od.Ordernumber" could not be bounds"
"The multi-part identifier "od.Location_code" could not be bounds"
create function Mbse.udf_ordertotal
(#Numberoforder int , #loction_code int )
returns int
as
begin
declare #amount as int
set #amount=(select sum(od.amount) from Mbse.OrderDetails as od
where (#Numberoforder=od.Ordernumber and #loction_code=od.Location_code)
)
return #amount
end
alter table Mbse.orders
add amount as Mbse.udf_ordertotal(Mbse.OrderDetails.Ordernumber , Mbse.OrderDetails.location_code)
i expect solve for this problem please
Like Jeff said in the comments, your computed column using a user-defined function to aggregate the Mbse.OrderDetails table is not a good idea for multiple reasons. It'll be heavy, will process RBAR (row by agonizing row) aka once per every row, and will prevent parallelism for any queries that reference that function or your Mbse.orders table directly or even indirectly.
You'd be better off with proper indexing on your OrderDetails table and a view that joins it to your Orders table like so:
-- Columnstore indexes are typically very quick for aggregative queries
CREATE NONCLUSTERED COLUMNSTORE INDEX IX_OrderDetails_Amount ON Mbse.OrderDetails (Ordernumber, Location_code, amount);
CREATE VIEW Mbse.OrdersWithTotals
AS
WITH _OrderDetailsTotals AS
(
SELECT
Ordernumber,
Location_code,
SUM(amount) AS TotalAmount
FROM Msbe.OrderDetails
GROUP BY
Ordernumber,
Location_code
)
SELECT
O.Ordernumber,
O.location_code,
ODT.TotalAmount
FROM Mbse.orders AS O
LEFT JOIN _OrderDetailsTotals AS ODT
ON O.Ordernumber = ODT.Ordernumber
AND O.location_code = ODT.Location_code;
Related
We faced with unpredictable duration of executing our code. The same query can take less than a second, or more than a minute. It looks like our attempt to use MySQL JSON_ functions probably was not a good idea.
select p.pk,
p.name,
... /* fields from primary table */
(SELECT JSON_ARRAYAGG(CODE)
FROM (SELECT region.region_pk AS CODE
FROM program_region region
WHERE region.program_pk = p.pk) AS a)
AS region_codes,
(SELECT JSON_ARRAYAGG(CODE)
FROM (SELECT affiliate.affiliate_pk AS CODE
FROM program_affiliate affiliate
WHERE affiliate.program_pk = p.pk) AS a) AS affiliate_codes,
(SELECT JSON_ARRAYAGG(user_id)
FROM (SELECT DISTINCT user_id
FROM (SELECT role.user_id
FROM program_role role
WHERE role.program_pk = p.pk
UNION ALL
SELECT p.created_by) AS us) AS a) AS user_ids
from program p;
Structure:
program:
pk bigint,
name varchar ...
program_affiliate and other child tables
pk bigint,
program_pk bigint /* FK with index */
code varchar(20)
...
We checked another queries works as usual but only new ones has these issues.
Does anybody else faced with performance issues with JSON functions before? Any recommendations?
Okay so I have two tables:
hscust and hssales_rep
I need to create a view that shows me the reps fname and lname (as well as the customers) and show how much the customer is over on there credit balance.
This is the code I have:
CREATE VIEW OverLimit AS
SELECT
CONCAT(hssales_rep.last,hssales_rep.first) AS Rep,
CONCAT(hscust.last,hscust.first) AS Cust,
SUM(credit_limit - balance)
FROM hscust
INNER JOIN hssales_rep ON hscust.sales_rep = hssales_rep.repid
And it returns an empty result.
Any help is greatly appreciated!
salesrep table
cust table
A CREATE VIEW statement doesn't return a resultset.
A SELECT statement can return an empty resultset. But we'd expect the SELECT statement in your view definition to return either a single row, or throw an error.
I suggest you break this down a bit.
1) What problem is being solved by the CREATE VIEW statement. Why do you need a view?
2) Before you write a CREATE VIEW statement, first develop and test a SELECT statement that returns the required resultset. Do that before you put that into a view definition.
I also strongly recommend that you qualify all column references in the SELECT statement either with the table name or (preferably) a short table alias.
If you want to return a row for each Cust with an aggregate function (e.g. SUM) in your SELECT list, then add an appropriate GROUP BY clause to your SELECT statement.
It's not clear why we would want to use a SUM aggregate function.
The difference between "credit_limit" and "balance" would be the available (remaining) credit. A negative value would indicate the balance was "over" the credit limit.
SELECT CONCAT(r.last,r.first) AS Rep
, CONCAT(c.last,c.first) AS Cust
, c.credit_limit - c.balance AS available_credit
FROM hscust c
JOIN hssales_rep r
ON c.sales_rep=r.repid
ORDER
BY CONCAT(r.last,r.first)
, CONCAT(c.last,c.first)
, c.custid
If we only want to return rows for customers that are "over" their credit limit, we can add a WHERE clause.
SELECT CONCAT(r.last,r.first) AS Rep
, CONCAT(c.last,c.first) AS Cust
, c.credit_limit - c.balance AS available_credit
FROM hscust c
JOIN hssales_rep r
ON c.sales_rep=r.repid
WHERE c.credit_limit - c.balance < 0
ORDER
BY CONCAT(r.last,r.first)
, CONCAT(c.last,c.first)
, c.custid
Again, get a SELECT statement working (returning the required resultset) before you wrap it in a CREATE VIEW.
I was able to write two SQL queries, first one is an Inline Table Valued Function(ITVF) and the latter is a Multistatement Table Valued Function(MTVF) for the same task which is quering the worktime of certain employees.
-------------- Inline Table Valued Function (ITVF) ---------------------
CREATE FUNCTION fn_ITVF_GetWorkTimes()
RETURNS TABLE
AS RETURN( SELECT E.ID, E.Name, E.DepartmentID, R.TotalTime
FROM tblEmployee E
INNER JOIN
( SELECT T.Id, CAST(DATEDIFF(MINUTE,StartTime,EndTime)/60.0 as DECIMAL(18,2)) AS 'TotalTime'
FROM tblTimeRecord T) AS R
ON E.ID = R.Id )
SELECT * FROM fn_ITVF_GetWorkTimes();
--------------- Multi-Statement Table Valued Functions (MTVF) -------------------
CREATE FUNCTION fn_MTVF_GetEmployeeTimes()
RETURNS #Table1 TABLE(Id INT,Name NVARCHAR(50),DepartmentID INT,TimeWork DECIMAL(18,2))
AS
BEGIN
INSERT INTO #Table1
SELECT E.Id, E.Name, E.DepartmentId, R.TotalTime
FROM tblEmployee AS E
INNER JOIN
(SELECT T.ID, CAST(DATEDIFF(MINUTE,T.StartTime,T.EndTime)/60.0 as DECIMAL (18,2)) AS 'TotalTime'
FROM tblTimeRecord AS T) AS R
ON E.Id=R.ID
RETURN
END
SELECT * FROM dbo.fn_MTVF_GetEmployeeTimes();
I am aware that few questions have been raised on this topic earlier, but still i could not find out a scenario which only a MultiStatement Table Valued Function can be applied and is there a clear reason why an ITVF cannot be applied for such a scenario ? According to my research it has been advised to use ITVF all the time if it is possible and it seems it is more efficient than MTVF as well. If it is true why would anyone tend to use MTVF ? Clear explantion with examples would be highly appreciated.
Apart from the syntax the main limitation between IVTF and MVTF is that IVTF can only have A Single Select Statement same as views.
Whereas on the other hand MVTF can have a more complex logic inside them. IF/Else blocks etc.
Some say IVTF can be seen as Parameterised Views and MVTF can be seen as Stored procedures you can select from.
I am running into some trouble with the following circumstances:
I have a query that creates two temp tables, and the following select to join them together--
SELECT * FROM result
INNER JOIN result2 ON result2.packetDetailsId = result.packetDetailsId
I am then trying to create another column from concatenating a few of the resulting fields and then use that to reference/query against another table. Is there a way to accomplish this in one query? Should I get away from the temp tables?
Thank you again in advance.
update: If I try to alias the combination of the two temp tables I get an error message stating [Err] 1060 - Duplicate column name 'packetDetailsId'
select * from (
SELECT * FROM result
INNER JOIN result2 ON result2.packetDetailsId = result.packetDetailsId) as myalias
Another Update: I almost have it working as one query but I get the result "(BLOB)" in the column I concoctenated:
select packet_details.packetDetailsId,products.productId,Credit,AccountNum,OrderStat, CONCAT(products.productId,Credit,'_',OrderStat) as consol from (
select packetDetailsId, GROUP_CONCAT(Credit) AS Credit, GROUP_CONCAT(AccountNum) AS AccountNum, GROUP_CONCAT(OrderStat) AS OrderStat FROM
( SELECT pd_extrafields.packetDetailsId,
CASE WHEN pd_extrafields.ex_title LIKE ('%Credit%')
THEN pd_extrafields.ex_value ELSE NULL END as Credit,
CASE WHEN pd_extrafields.ex_title LIKE ('%Account%')
THEN pd_extrafields.ex_value ELSE NULL END as AccountNum,
CASE WHEN pd_extrafields.ex_title LIKE ('%Existing%')
THEN pd_extrafields.ex_value ELSE NULL END as OrderStat
FROM pd_extrafields )AS TempTab GROUP BY packetDetailsId ) as alias2
INNER JOIN packet_details ON alias2.packetDetailsId = packet_details.packetDetailsId
INNER JOIN sales ON packet_details.packetDetailsId = sales.packetDetailsId
INNER JOIN sold_products ON sales.saleId = sold_products.saleId
INNER JOIN products ON sold_products.productId = products.productId
If I understand correctly, you already have the temporary tables created and you need to "concatenate" the results, using from ... inner join ...
The only possible restriction you may have is that you can only reference your temporary tables once in your from clause; besides that, there are no other restrictions (I frequently use temporary tables as intermediate steps in the creation of my final result).
Tips
Let's say your temp tables are temp_result1 and temp_result2. Both tables have a field packedDetailsId, on which the join will be performed. Remember to create the appropriate indexes on each table; at the very least you need to index packedDetailsId on both tables:
alter table temp_result1
add index PDI(packedDetailsId);
alter table temp_result2
add index PDI(packedDetailsId);
Now, just execute a query with the desired join and concatenation. If concat returns BLOB, then cast the result as char (of course, I'm assuming you need a text string):
select r1.*, r2.*, cast(concat(r1.field1, ',', r2.field2) as char) as data_concat
from temp_result1 as r1
inner join temp_result2 as r2 on r1.packedDetailsId = r2.packedDetailsId;
I see your problem is that GROUP_CONCAT is returning BLOB values... It's normal (MySQL doesn't know a priori how to return the values, so it returns binary data); just use the cast function.
Hope this helps you
so, if the result2 and result are both temp tables, you will have to include the # if local temp table and ## if global temp table
so your statements should be :
SELECT * FROM #result
INNER JOIN #result2 ON #result2.packetDetailsId = #result.packetDetailsId
My Bad. This is only applicable for MS SQL
I have a table defined like the following...
CREATE table actions (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
end BOOLEAN,
type VARCHAR(15) NOT NULL,
subtype_a VARCHAR(15),
subtype_b VARCHAR(15),
);
I'm trying to query for the last end action of some type to happen on each unique (subtype_a, subtype_b) pair, similar to a group by (except SQLite doesn't say what row is guaranteed to be returned by a group by).
On an SQLite database of about 1MB, the query I have now can take upwards of two seconds, but I need to speed it up to take under a second (since this will be called frequently).
example query:
SELECT * FROM actions a_out
WHERE id =
(SELECT MAX(a_in.id) FROM actions a_in
WHERE a_out.subtype_a = a_in.subtype_a
AND a_out.subtype_b = a_in.subtype_b
AND a_in.status IS NOT NULL
AND a_in.type = "some_type");
If it helps, I know all the unique possibilities for a (subtype_a,subtype_b)
eg:
(a,1)
(a,2)
(b,3)
(b,4)
(b,5)
(b,6)
Beginning with version 3.7.11, SQLite guarantees which record is returned in a group:
Queries of the form: "SELECT max(x), y FROM table" returns the value of y on the same row that contains the maximum x value.
So greatest-n-per-group can be implemented in a much simpler way:
SELECT *, max(id)
FROM actions
WHERE type = 'some_type'
GROUP BY subtype_a, subtype_b
Is this any faster?
select * from actions where id in (select max(id) from actions where type="some_type" group by subtype_a, subtype_b);
This is the greatest-in-per-group problem that comes up frequently on StackOverflow.
Here's how I solve it:
SELECT a_out.* FROM actions a_out
LEFT OUTER JOIN actions a_in ON a_out.subtype_a = a_in.subtype_a
AND a_out.subtype_b = a_in.subtype_b
AND a_out.id < a_in.id
WHERE a_out.type = "some type" AND a_in.id IS NULL
If you have an index on (type, subtype_a, subtype_b, id) this should run very fast.
See also my answers to similar SQL questions:
Fetch the row which has the Max value for a column
Retrieving the last record in each group
SQL join: selecting the last records in a one-to-many relationship
Or this brilliant article by Jan Kneschke: Groupwise Max.