I want to use data of view in WHERE clause. But getting an error:
create view post_with_answers AS
SELECT DISTINCT postid
FROM (SELECT postid FROM `qa_posts` WHERE `type` = 'Q') AS q1
INNER JOIN (SELECT parentid FROM `qa_posts` WHERE `type` = 'A') AS q2 ON q1.postid = q2.parentid
select count(*)
from qa_posts
where parentid not in post_with_answers
On the last row I am getting this error:
SQL Error [1064] [42000]: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'post_with_answers' at line 3
How to fix that?
Just like you would use a table:
select count(*)
from qa_posts
where parentid not in (select pwa.postid from post_with_answers pwa);
I would caution you from using not in with a subquery. No rows are returned if even one value from the subquery is NULL. For this reason, I recommend NOT EXISTS:
select count(*)
from qa_posts p
where not exists (select 1
from post_with_answers pwa
where p.parentid = pwa.postid
);
In addition, your view definition is a bit over complicated. You don't need subqueries:
create view post_with_answers AS
SELECT DISTINCT pq.postid
FROM qa_posts pq JOIN
qa_posts pa
ON pq.postid = pa.parentid
WHERE pq.type = 'Q' AND pa.type = 'A';
Then, the DISTINCT just adds overhead, so EXISTS is better:
create view post_with_answers AS
SELECT DISTINCT pq.postid
FROM qa_posts pq
WHERE EXISTS (SELECT 1
FROM qa_posts pa
WHERE pq.postid = pa.parentid AND
pa.type = 'A'
)
WHERE pq.type = 'Q';
We have a Web Api service for report building. This service uses MS SQL 2008 database as a data source. The data base works as a mirror in readonly mode.
The service and the database are hosted on different computers of a single local net.
There is a stored procedure in the database named TicketSaleByAggregator, that selects report data. Sometimes the procedure throws following exception:
System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out
Then the procedure is throwing this exception again and again until we recompile it:: ALTER PROCEDURE [dbo] [TicketSaleByAggregator].
After the command ALTER PROCEDURE, the procedure runs perfectly even on big data sets, but after about 10-15 hours the error throws again: Timeout expired
The procedure parameters:
DECLARE #PeriodFrom DATETIME = '2016-12-30 00:00:00'
DECLARE #PeriodTo DATETIME = '2016-12-30 23:59:59'
DECLARE #Dealers Identities
DECLARE #Branches Identities
DECLARE #SaleChannels Identities
DECLARE #Carriers Identities
INSERT INTO #Dealers (Id) VALUES(10068)
INSERT INTO #Branches(Id) VALUES(1),(2),(3)
INSERT INTO #SaleChannels(Id)VALUES (7)
exec TicketSaleByAggregator #PeriodFrom, #PeriodTo, #Dealers, #Branches, #SaleChannels, #Carriers
If we call the procedure locally (on the machine where it is hosted) in SQL Management Studio, then it executes for 15 seconds
If we call the procedure on the machine where the web api service is hosted, in SQL Management Studio, then it executes for 15-16 seconds
.The Result data contains 82540 records
Code of stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[TicketSaleByAggregator]
(
#PeriodFrom DATETIME,
#PeriodTo DATETIME,
#Dealers Identities READONLY,
#Branches Identities READONLY,
#SaleChannels Identities READONLY,
#Carriers Identities READONLY
)
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SET NOCOUNT ON
;WITH ParentDealer(childId, parentId, BIN)
AS(
SELECT d.Id,
parentDealer.pId,
parentDealer.BIN
FROM Dealer AS d
JOIN (
SELECT d.Id,
parentDealer.Id pId,
parentDealer.BIN
FROM Dealer d
JOIN Dealer parentDealer
ON parentDealer.Hid = d.Hid.GetAncestor(d.[Hid].[GetLevel]() -1)
) parentDealer
ON d.Id = parentDealer.Id
),
CarrierNames
AS(
SELECT c.Name AS CarrierName
FROM Carrier AS c
INNER JOIN #Carriers crs ON c.Id = crs.Id
),
Result
AS(
SELECT *
FROM
(
SELECT t.[ExpressId] AS TicketExpressId,
o.[OrderCreateDate] AS OperationDate,
1 AS TicketCount,
t.[Tariff] AS Tariff,
6 AS OperationTypeId,
sc.Name AS SalesChannelName,
b.ShortName AS BranchName,
o.CarrierName,
o.PaymentType AS PaymentType,
--financial dealers
uDealer.Surname AS FinancialDealerSurname,
uDealer.Name AS FinancialDealerName,
uDealer.Middlename AS FinancialDealerPatronymic,
d.BIN AS FinancialDealerBin,
uparentDealer.Surname AS FinancialParentDealerSurname,
uparentDealer.Name AS FinancialParentDealerName,
uparentDealer.Middlename AS FinancialParentDealerPatronymic,
parentDealer.BIN AS FinancialParentDealerBin,
--place dealers
uDealer.Surname AS PlaceDealerSurname,
uDealer.Name AS PlaceDealerName,
uDealer.Middlename AS PlaceDealerPatronymic,
d.BIN AS PlaceDealerBin,
uparentDealer.Surname AS PlaceParentDealerSurname,
uparentDealer.Name AS PlaceParentDealerName,
uparentDealer.Middlename AS PlaceParentDealerPatronymic,
parentDealer.BIN AS PlaceParentDealerBin
FROM Ticket AS t
INNER JOIN [Order] AS o ON o.Id = t.OrderId AND o.OrderCreateDate BETWEEN #PeriodFrom AND #PeriodTo
INNER JOIN [Terminal] AS ter ON t.[TerminalId] = ter.[Id]
LEFT JOIN [TerminalData] AS td ON ter.[Id] = td.[Id]
INNER JOIN [SalePoint] AS sp ON td.[SalePointId] = sp.[Id]
INNER JOIN FinAccStation AS fas ON fas.Id = sp.FinAccStationId
INNER JOIN Guo AS g ON g.Id = fas.GuoId
INNER JOIN Department AS dep ON dep.Id = g.DepartmentId
INNER JOIN Dealer AS d ON d.Id = ter.DealerId
INNER JOIN [User] AS uDealer ON uDealer.Id = d.Id
INNER JOIN SalesChannel AS sc ON sc.Id = d.SalesChannelId AND (EXISTS(SELECT * FROM #SaleChannels) AND (d.SalesChannelId IN (SELECT * FROM #saleChannels)) OR NOT EXISTS(SELECT * FROM #saleChannels))
INNER JOIN Branch AS b ON b.Id = dep.BranchId AND (EXISTS(SELECT * FROM #Branches) AND (b.Id IN (SELECT * FROM #Branches)))
INNER JOIN ParentDealer AS parentDealer ON parentDealer.childId = d.Id AND (parentDealer.parentId IN (SELECT Id FROM #Dealers) OR NOT EXISTS(SELECT * FROM #Dealers))
INNER JOIN [User] AS uParentDealer ON uParentDealer.Id = parentDealer.parentId
WHERE t.TicketStatusId IN (3, 6) AND
((EXISTS(SELECT TOP 1 * FROM #Carriers) AND (o.CarrierName IN (SELECT CarrierName FROM CarrierNames))) OR NOT EXISTS(SELECT TOP 1 * FROM #Carriers))
UNION ALL
SELECT t.[ExpressId] AS TicketExpressId,
c.OperationDate AS OperationDate,
-1 AS TicketCount,
(-1)*ct.RetTariff AS Tariff,
3 AS OperationTypeId,
sc.Name AS SalesChannelName,
b.ShortName AS BranchName,
o.CarrierName,
c.PaymentType AS PaymentType,
--financial dealers
uDealer.Surname AS DealerSurname,
uDealer.Name AS DealerName,
uDealer.Middlename AS DealerPatronymic,
d.BIN AS DealerBin,
uparentDealer.Surname AS ParentDealerSurname,
uparentDealer.Name AS ParentDealerName,
uparentDealer.Middlename AS ParentDealerPatronymic,
parentDealer.BIN AS ParentDealerBin,
--place dealers
uDealer1.Surname AS PlaceDealerSurname,
uDealer1.Name AS PlaceDealerName,
uDealer1.Middlename AS PlaceDealerPatronymic,
d1.BIN AS PlaceDealerBin,
uparentDealer1.Surname AS PlaceParentDealerSurname,
uparentDealer1.Name AS PlaceParentDealerName,
uparentDealer1.Middlename AS PlaceParentDealerPatronymic,
parentDealer1.BIN AS PlaceParentDealerBin
FROM Cancelation AS c
INNER JOIN CancelationTicket AS ct ON ct.CancelationId = c.Id
INNER JOIN Ticket AS t ON t.Id = ct.TicketId
INNER JOIN [Order] AS o ON o.Id = c.OrderId
INNER JOIN Terminal AS ter ON ter.Id = IIF(o.PaymentType = 1, c.TerminalId, t.TerminalId)
INNER JOIN Terminal AS ter1 ON ter1.Id = c.TerminalId
LEFT JOIN [TerminalData] AS td ON td.[Id] = ter.Id
INNER JOIN [SalePoint] AS sp ON td.[SalePointId] = sp.[Id]
INNER JOIN FinAccStation AS fas ON fas.Id = sp.FinAccStationId
INNER JOIN Guo AS g ON g.Id = fas.GuoId
INNER JOIN Department AS dep ON dep.Id = g.DepartmentId
INNER JOIN Dealer AS d ON d.Id = ter.DealerId
INNER JOIN Dealer AS d1 ON d1.Id = ter1.DealerId
INNER JOIN [User] AS uDealer ON uDealer.Id = d.Id
INNER JOIN [User] AS uDealer1 ON uDealer1.Id = d1.Id
INNER JOIN SalesChannel AS sc ON sc.Id = d.SalesChannelId AND (EXISTS(SELECT * FROM #SaleChannels) AND (d.SalesChannelId IN (SELECT * FROM #saleChannels)) OR NOT EXISTS(SELECT * FROM #saleChannels))
INNER JOIN Branch AS b ON b.Id = dep.BranchId AND (EXISTS(SELECT * FROM #Branches) AND (b.Id IN (SELECT * FROM #Branches)))
INNER JOIN ParentDealer AS parentDealer ON parentDealer.childId = d.Id AND (parentDealer.parentId IN (SELECT Id FROM #Dealers) OR NOT EXISTS(SELECT * FROM #Dealers))
INNER JOIN [User] AS uParentDealer ON uParentDealer.Id = parentDealer.parentId
INNER JOIN ParentDealer AS parentDealer1 ON parentDealer1.childId = d1.Id
INNER JOIN [User] AS uParentDealer1 ON uParentDealer1.Id = parentDealer1.parentId
WHERE c.OperationDate BETWEEN #PeriodFrom AND #PeriodTo AND
((EXISTS(SELECT TOP 1 * FROM #Carriers) AND (o.CarrierName IN (SELECT CarrierName FROM CarrierNames))) OR NOT EXISTS(SELECT TOP 1 * FROM #Carriers)) AND
c.ResponseXml.value('(/GtETicket_Response/#Type)[1]','nvarchar(max)') != 'ExpressStatus'
)T
)
SELECT *
from Result
END
UPDATED: Code on C# side:
public IEnumerable<RegisterTicketsByDealerReportItem> GetRegisterTicketsByDealerReport(DateTime periodFrom, DateTime periodTo, int[] dealerIds, int[] salesChannelIds, int[] branchIds, int[] carrierIds)
{
var pars = new DynamicParameters();
var identityFailureValue = new { Id = 0 }.ToEmptyTable().AsTableValuedParameter("Identities");
pars.AddDynamicParams(
new
{
PeriodFrom = periodFrom,
PeriodTo = periodTo,
Dealers = dealerIds.Return(ds => ds.Select(d => new { Id = d }).ToDataTable().AsTableValuedParameter("Identities"), identityFailureValue),
Branches = branchIds.Return(br => br.Select(b => new { Id = b }).ToDataTable().AsTableValuedParameter("Identities"), identityFailureValue),
SaleChannels = salesChannelIds.Return(scs => scs.Select(sc => new { Id = sc }).ToDataTable().AsTableValuedParameter("Identities"), identityFailureValue),
Carriers = carrierIds.Return(scs => scs.Select(sc => new { Id = sc }).ToDataTable().AsTableValuedParameter("Identities"), identityFailureValue)
});
var result = Connection.Query<RegisterTicketsByDealerReportItem>("TicketSaleByAggregator", pars,
commandType: CommandType.StoredProcedure,
commandTimeout: dbConfiguration.SqlLargeTimeoutSeconds);
Connection.CloseIfNoTransaction();
return result;
}
Sql connection parametrs:
<add key="SqlLargeTimeoutSeconds" value="00:02:00" />
<add name="Readonly" providerName="System.Data.SqlClient" connectionString="Data Source=.;Initial Catalog=db_Readonly;Integrated Security=True;" />
1- Try to use with(nolock) if it is non sensitive transnational data
2- Stop mirroring and check the speed. mirroring may cause this problem
I Have a Query in mysql like this:
select
t1.id_invoice_in, t1.paymentcode, t1.personname, t1.amount,
t2.id_invoice_out, t2.paymentcode, t2.personname, t2.amount
from (
select
id_invoice_in, paymentcode, personname, amount,
(#r1 := #r1 + 1) as r1
from invoice_in
join paymenttype pt on pt.id = paymenttype_id
join persons p on p.id = person_id
,(select #r1 := 0) r
) t1 left join (
select
id_invoice_out, paymentcode, personname, amount,
(#r2 := #r2 + 1) as r2
from invoice_out
join paymenttype pt on pt.id = paymenttype_id
join persons p on p.id = person_id
,(select #r2 := 0) r
) t2 on t1.r1 = t2.r2;
Sample SQL Fiddle
That query working fine on phpmyadmin. When i put the query in VB.net like this:
myCMD = New MySqlCommand(strQuery, MysqlConn)
mysqlReader = myCMD.ExecuteReader()
i got the error: "fatal error encountered during command execution" from exception message.
i guess maybe the query containt this symbol '#', so i must write myCMD.Parameters.AddWithValue("#", something else). *correct me if im wrong.
the question is, how vb.net by pass the query without entry myCMD.Parameters.AddWithValue. So vb.net just running the query without must entry '#' value, because no value for '#'.
I'm having an issue with the following query
select
ord.order_id,
ordProduct.product_id,
coupProd.product_id,
coup.date_end as DateEnd, coup.coupon_id
from `order` ord
inner join order_product ordProduct on ord.order_id = ordProduct.order_id
inner join coupon_product coupProd on ordProduct.product_id = coupProd.product_id
inner join coupon coup on coupProd.coupon_id = coup.coupon_id
where (coup.date_end > curdate());
If I remvove the where clause, the query executes fine, otherwise it just hangs. Any ideas?
It's not a solution per se, but as a workaround, you could maybe get it done as a nested query. i.e. ,
SELECT * FROM (
SELECT
ord.order_id,
ordProduct.product_id,
coupProd.product_id,
coup.date_end AS DateEnd, coup.coupon_id
FROM `order` ord
INNER JOIN order_product ordProduct ON ord.order_id = ordProduct.order_id
INNER JOIN coupon_product coupProd ON ordProduct.product_id = coupProd.product_id
INNER JOIN coupon coup ON coupProd.coupon_id = coup.coupon_id)
WHERE (DateEnd > CURDATE());
Here is my sp query:
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`#`%` PROCEDURE `USP_GetUserOrders`(UserId INT)
BEGIN
SELECT op.OrderId,
O.Number,
SUM(op.Price) Price,
(SELECT CONCAT(A.Detail, ' ',C.Name, ' / ', Ci.Name) FROM kobiakinlar.Address AS A
INNER JOIN County AS C ON C.CountyId = A.CountyId
INNER JOIN City AS Ci ON C.CityId = Ci.CityId
WHERE UserId = O.UserId) AS UserAddress,
( SELECT CASE WHEN O.Status =0 THEN 'Onay Bekliyor' WHEN O.Status =1 THEN 'Onaylandı' WHEN O.Status = 2 THEN 'Reddedildi' END) Status,
O.Creation,
( SELECT CASE WHEN O.IsDelivered =0 THEN 'Teslim Edilmedi' ELSE 'Teslim Edildi' END) IsDelivered,
group_concat(P.Name) Product
FROM
kobiakinlar.product P
JOIN
kobiakinlar.orderproduct op ON op.ProductId = P.productId
JOIN
kobiakinlar.order O ON O.orderId = op.OrderId
JOIN
kobiakinlar.address A ON A.addressId = O.AddressId
WHERE O.UserId = UserId
GROUP BY op.OrderId;
END
It returns Error Code: 1242. Subquery returns more than 1 row when I CALL USP_GetUserOrders(3)
But I run only sql in query tab, it runs and return what I want. You can see query's result in image:
Do you have any suggestion?
I'm pretty sure the reason is the confusion between UserId and o.UserId.
In the query context, it does not know that you mean the argument to the sp. Change the name of the arguemnt to something like "arg_UserId" and substitute that in the query where appropriate.
You can also simplify your query syntax. The SELECT outside the case statements is redundant. Also, assuming that the joins to County and City are always 1-1, you can rewrite the query as:
SELECT op.OrderId, O.Number, SUM(op.Price) Price,
CONCAT(A.Detail, ' ', C.Name, ' / ', Ci.Name) AS UserAddress,
(CASE WHEN O.Status =0 THEN 'Onay Bekliyor' WHEN O.Status =1 THEN 'Onaylandı' WHEN O.Status = 2 THEN 'Reddedildi' END) Status,
O.Creation,
(CASE WHEN O.IsDelivered =0 THEN 'Teslim Edilmedi' ELSE 'Teslim Edildi' END) IsDelivered,
group_concat(P.Name) as Product
FROM kobiakinlar.product P JOIN
kobiakinlar.orderproduct op
ON op.ProductId = P.productId JOIN
kobiakinlar.order O
ON O.orderId = op.OrderId JOIN
kobiakinlar.address A ON A.addressId = O.AddressId join
County C
ON C.CountyId = A.CountyId join
City AS Ci
ON C.CityId = Ci.CityId
WHERE O.UserId = arg_UserId
GROUP BY op.OrderId;