I am trying desperately to avoid a foreach situation in SQL Server 2008 (my background is in c#).
Basically, I have a list of SKUs. For each SKU in the list, I need to perform some calculations that determine if that particular SKU will be displayed on the web.
To get my list of SKUs, I use this:
SELECT Feed.StyleCode as SKU
FROM [eCommerce].[dbo].[BABW_ItemFeed] as Feed
WHERE Feed.ProductDefinition = 'Kit'
Returning this:
And to calculate each SKUs fields, I've been using this:
DECLARE #SKU AS varchar(50)
SET #SKU= '11993_16559_16227'
SELECT
#SKU as SKU,
0 AS Quantity,
MIN(ISNULL(Sending.IsActive, 'WEBNO')) AS IsActive,
MAX(ISNULL(Sending.IsDiscontinued, 1)) AS IsDiscontinued
FROM
(
SELECT * FROM [eCommerce].[dbo].[Split] (
#SKU
,'_')
) AS SplitSkus
LEFT JOIN #SkusToSend AS Sending
ON Sending.SKU = SplitSkus.items
Returning this:
Now I need to synch the two tables together, removing the #SKU declaration. I don't think I'm able to use a UNION to do this, because the second function requires fore-knowledge of the SKU it will be processing... and a JOIN would require something to join on, which I don't really have. Is there some function I'm not familiar with that I can use to create a complete table of SKUs in one go without a looping mechanism?
Try a CROSS APPLY... which will execute your UDF for each row in BABW_ItemFeed:
SELECT
Feed.StyleCode as SKU,
COUNT(*) AS Quantity,
MIN(ISNULL(Sending.IsActive, 'WEBNO')) AS IsActive,
MAX(ISNULL(Sending.IsDiscontinued, 1)) AS IsDiscontinued
FROM
[eCommerce].[dbo].[BABW_ItemFeed] as Feed
CROSS APPLY [eCommerce].[dbo].[Split] (Feed.StyleCode, '_') AS SplitSkus
LEFT JOIN #SkusToSend AS Sending
ON Sending.SKU = SplitSkus.items
WHERE
Feed.ProductDefinition = 'Kit'
GROUP BY
Feed.StyleCode
Stop using Min() and Max()...or else, pull SKU (don't use the parameter in the SELECT).
Try This:
SELECT
SKU,
0 AS Quantity,
MIN(ISNULL(Sending.IsActive, 'WEBNO')) AS IsActive,
MAX(ISNULL(Sending.IsDiscontinued, 1)) AS IsDiscontinued
FROM
(
SELECT [eCommerce].[dbo].[Split] (Feed.StyleCode,'_') as SKU
FROM [eCommerce].[dbo].[BABW_ItemFeed] as Feed
WHERE Feed.ProductDefinition = 'Kit'
) AS SplitSkus
LEFT JOIN #SkusToSend AS Sending
ON Sending.SKU = SplitSkus.items
Related
I have the following scenario: I am trying to pass result of one query to another , In this case I am trying to pass view_id in another query since this are ids they are unique and cant be duplicate in any case .
select view_id from view where view_query_id = "18711987173"
select queue_id from queue where queue_view = view_id
`
I saw some examples and I tried executing them something like as
select view_id from view where view_query_id = "18711987173 exists (select queue_id from queue where queue_view = view.view_id)
But surely this didnt helped :)
You can use a common table expression
WITH temp AS (SELECT view_id FROM view WHERE view_query_id = "18711987173")
SELECT queue_id FROM queue q INNER JOIN temp t ON q.queue_id = t.view_id;
This should work regardless of what relationship is between those tables. You can replace the JOIN by WHERE..IN, but this way seems cleaner and takes care if the no. of values in IN becomes too large.
Use table expression
WITH temp AS (SELECT view_id FROM view WHERE view_query_id = "18711987173")
SELECT queue_id FROM queue q INNER JOIN temp t ON q.queue_id = t.view_id;
I got a hash map in java like this
{(1,'2018-06-29 10:19:33'),(4,'2018-06-29 10:19:34'),(10,'2018-06-29 10:19:38'),....}
The length of map could go as high as 3000
and a mysql table
id name updated
1, firstProduct, 2018-06-29 09:19:33
2, secondproduct, 2014-06-29 10:19:33
4, fourthproduct, 2016-06-29 09:19:33
10, tenthproduct, 2018-06-29 06:13:32
.......
the key in the map is a id field in the table and the value is the updated timestamp field.
I would like to get all the products in the table whose timestamp is greater that value in the map.
like
select * from products where id = 1 and updated > '2018-06-29 10:19:33'
select * from products where id = 4 and updated > '2018-06-29 10:19:34'
...
But there could be as many as 3000 entries in the map.
I am thinking of passing the map values to mysql stored procedure. Inside the procedure a while loop will execute select statement for each map entry into a result set and finally return the result set back to java program.
Would like to know if this is possible and i feel there is a better solution for this but cant figure out.
I would dynamically generate a statement in Java.
Either:
SELECT p.id, p.name, p.update
FROM products p
WHERE 1=0
OR ( p.id = ? AND updated > ? )
OR ( p.id = ? AND updated > ? )
OR ( p.id = ? AND updated > ? )
(MySQL likely won't make effective use of an index for that query.)
Or, we could do :
SELECT p.id, p.name, p.update FROM products p WHERE p.id = ? AND updated > ?
UNION ALL
SELECT p.id, p.name, p.update FROM products p WHERE p.id = ? AND updated > ?
UNION ALL
SELECT p.id, p.name, p.update FROM products p WHERE p.id = ? AND updated > ?
With an appropriate index defined, each SELECT could make effective use of that. But with this approach, we are probably going to hit an upper limit on the number of table references in a single query. So this approach may need to be broken up into chunks.
Personally, I wouldn't hide the complexity in a database procedure.
It's not clear what benefit we would gain by implementing a database procedure.
I have two tables incoming_sms and subscribers_register that stores all of the numbers of customers.The table incoming_sms has lots of data from very many numbers but i would only want to select messages by my subscribers.
I have this query i am trying to use to show only messages from my subscribers but returns 0 results
SELECT dest_msisdn, text_message FROM incoming_sms where dest_msisdn in (SELECT GROUP_CONCAT(msisdn) FROM subscribers_register);
Why am i getting 0 results?.
Have a look at the help for GROUP_CONCAT. It's going to return a long string of all the msisdn's instead of a list of all the msisdn's.
You could do something like this:
SELECT
dest_msisdn,
text_message
FROM incoming_sms
WHERE dest_msisdn in
(SELECT msisdn FROM subscribers_register)
... or you may find that an inner join is faster to execute:
SELECT
dest_msisdn,
text_message
FROM incoming_sms
INNER JOIN subscribers_register
ON incoming_sms.dest_msisdn = subscribers_register.msisdn
ALTER Proc [dbo].[K_FS_GetBalanceforOrderconfirm]
#name varchar(50),
#date datetime
as
begin
select round(sum(DISTINCT AR.recamount) - sum(OD1.noofbags*MR.rateperkg*BG.bagtype),2) as balance from K_FS_AmountReceived AR inner join K_FS_OrderDetails1 OD1 on AR.orderno =OD1.ID
inner join K_FS_bagtype BG on BG.sno = OD1.bagtype
inner join k_FPS_FeedType FT on FT.sno = OD1.feedtype
inner join K_FS_FeedMrpDetails MR on FT.sno=MR.feedtype
where AR.Name = #name and MR.date = #date
end
Above query gives output based on date, but sum(.......) some values already have some date including that date sum(....) I want sum(......) based on whatever value been passed.
Your question in not clear to me. Are you trying to say that some tables are already have daily value summarized?
From my experience I would suggest to start with preparing data with intermediate subqueries. Something like
SELECT DISTINCT col1 FROM (SELECT * FROM RawData WHERE RowData.col1_date = #mydate) a
This way you can run subqueries independently and see what you get there.
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