how do i get multiple records from 1 record - sql

I have a product table with 15 fields like ItemID (primary),Name ,UPC,Price,Cost, etc.
Now I need to print labels the user can say
from Item "ABC" I need 15 labels
from item 'XYZ" I need 10 labels
I need a SQL statement which I will send the ItemID and the label Qty for Each record and it should give me back for each label a record for example 15 records for item "ABC" and 10 records for Item "XYZ" and so on

SELECT <fields>
FROM Mytable
Where Item = 'ABC'
GO 10
Will select those fields from that table 10 times in a row in 10 result sets.
Really though it sounds like you need to do what you are trying to do not in SQL, but in your calling application.

I agree this should be done on the client but if you insist, following duplicates each record 100 times and selects the amount you need from it.
;WITH ATable AS (
SELECT Item = 'ABC'
UNION ALL SELECT Item = 'XYZ'
)
, Temp (Item, Amount) AS (
SELECT 'ABC', 15
UNION ALL SELECT 'XYZ', 10
)
, q AS (
SELECT ID = 1
, Item
FROM ATable
UNION ALL
SELECT ID = q.ID +1
, q.Item
FROM q
WHERE ID < 100
)
SELECT q.*
FROM q
INNER JOIN Temp t ON t.Item = q.Item
AND t.Amount >= q.ID

You create the dynamic table aliased as r below. Works for amounts up to 2047.
select t.*
from
(select label='ABC', required=15 union all
select label='XYZ', required=10) r
inner join tbl t
on t.ItemID = r.label
inner join master..spt_values v
on v.type=Number and v.number between 1 and r.required
order by t.ItemID

Related

How to display null values in IN operator for SQL with two conditions in where

I have this query
select *
from dbo.EventLogs
where EntityID = 60181615
and EventTypeID in (1, 2, 3, 4, 5)
and NewValue = 'Received'
If 2 and 4 does not exist with NewValue 'Received' it shows this
current results
What I want
Ideally you should maintain somewhere a table containing all possible EventTypeID values. Sans that, we can use a CTE in place along with a left join:
WITH EventTypes AS (
SELECT 1 AS ID UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5
)
SELECT et.ID AS EventTypeId, el.*
FROM EventTypes et
LEFT JOIN dbo.EventLogs el
ON el.EntityID = 60181615 AND
el.NewValue = 'Received'
WHERE
et.ID IN (1,2,3,4,5);

How to add rows to a specific number multiple times in the same query

I already asked for help on a part of my problem here.
I used to get 10 rows no matter if there are filled or not. But now I'm facing something else where I need to do it multiple times in the same query result.
WITH NUMBERS AS
(
SELECT 1 rowNumber
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION ALL
SELECT 6
UNION ALL
SELECT 7
UNION ALL
SELECT 8
UNION ALL
SELECT 9
UNION ALL
SELECT 10
)
SELECT DISTINCT sp.SLC_ID, c.rowNumber, c.PCE_ID
FROM SELECT_PART sp
LEFT JOIN (
SELECT b.*
FROM NUMBERS
LEFT OUTER JOIN (
SELECT a.*
FROM (
SELECT SELECT_PART.SLC_ID, ROW_NUMBER() OVER (ORDER BY SELECT_PART.SLC_ID) as
rowNumber, SELECT_PART.PCE_ID
FROM SELECT_PART
WHERE SELECT_PART.SLC_ID = (must be the same as sp.SLC_ID and can''t hardcode it)
) a
) b
ON b.rowNumber = NUMBERS.rowNumber
) c ON c.SLC_ID = sp.SLC_ID
ORDER BY sp.SLC_ID, c.rowNumber
It works fine for the first 10 lines, but next SLC_ID only got 1 empty line
I need it to be like that
SLC_ID rowNumer PCE_ID
1 1 0001
1 2 0002
1 3 NULL
1 ... ...
1 10 NULL
2 1 0011
2 2 0012
2 3 0013
2 ... ...
2 10 0020
3 1 0021
3 ... ...
Really need it that way to build a report.
Instead of manually building a query-specific number list where you have to include every possible number you need (1 through 10 in this case), create a numbers table.
DECLARE #UpperBound INT = 1000000;
;WITH cteN(Number) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY s1.[object_id]) - 1
FROM sys.all_columns AS s1
CROSS JOIN sys.all_columns AS s2
)
SELECT [Number] INTO dbo.Numbers
FROM cteN WHERE [Number] <= #UpperBound;
CREATE UNIQUE CLUSTERED INDEX CIX_Number ON dbo.Numbers([Number])
WITH
(
FILLFACTOR = 100, -- in the event server default has been changed
DATA_COMPRESSION = ROW -- if Enterprise & table large enough to matter
);
Source: mssqltips
Alternatively, since you can't add data, use a table that already exists in SQL Server.
WITH NUMBERS AS
(
SELECT DISTINCT Number as rowNumber FROM master..spt_values where type = 'P'
)
SELECT DISTINCT sp.SLC_ID, c.rowNumber, c.PCE_ID
FROM SELECT_PART sp
LEFT JOIN (
SELECT b.*
FROM NUMBERS
LEFT OUTER JOIN (
SELECT a.*
FROM(
SELECT SELECT_PART.SLC_ID, ROW_NUMBER() OVER (ORDER BY SELECT_PART.SLC_ID) as
rowNumber, SELECT_PART.PCE_ID
FROM SELECT_PART
WHERE SELECT_PART.SLC_ID = (must be the same as sp.SLC_ID and can''t hardcode it)
) a
) b
ON b.rowNumber = NUMBERS.rowNumber
) c ON c.SLC_ID = sp.SLC_ID
ORDER BY sp.SLC_ID, c.rowNumber
NOTE: Max value for this solution is 2047

What should I do to print out the desired sql join result value?( SQL Join first match only)

I have two tables :
I want to use the chart_num value for two tables.
Table hospital_payment_data
id chart_num treatment_fees_difference treatment_fees_check_division
1 9 200000 test
2 9 -100000 test
3 10 200000 test
4 10 -100000 test
Table advenced_payment
id chart_num advenced_amount
1 9 100000
2 10 100000
I want result
if_treatment_fees_check_division sum_init_amount test COUNT
200000 200000 400000 4
However, when you send a query, the following results are printed.
SELECT
SUM(t_join.treatment_fees_difference) if_treatment_fees_check_division,
SUM(t_join.advenced_amount) sum_init_amount,
SUM(t_join.treatment_fees_difference) + SUM(t_join.advenced_amount) test,
COUNT(*) "count"
FROM
(
SELECT t_a.treatment_fees_difference , IFNULL(t_b.advenced_amount,0 ) AS advenced_amount
FROM hospital_payment_data t_a
LEFT OUTER JOIN advenced_payment t_b on t_a.chart_num = t_b.chart_num
WHERE t_a.treatment_fees_check_division = 'test'
) t_join
bad result
How do I fix my query to get the results I want?
The problem appears to be that you are joining the tables, which will give you two rows in the results, then you are summing the values with sum(t_join.advenced_amount) sum_init_amount which is giving double the value you want.
This is a quick and nasty fix:
SELECT
sum(t_join.treatment_fees_difference) if_treatment_fees_check_division,
MIN(t_join.advenced_amount) sum_init_amount ,
sum(t_join.treatment_fees_difference) + sum(t_join.advenced_amount) test,
COUNT(*) "count"
FROM
(
SELECT t_a.treatment_fees_difference , IFNULL(t_b.advenced_amount,0 ) AS advenced_amount
FROM hospital_payment_data t_a LEFT OUTER JOIN advenced_payment t_b on t_a.chart_num = t_b.chart_num
WHERE t_a.treatment_fees_check_division = 'test'
) t_join
But that will probably fail in a real world application.
Try it like this (untested):
SELECT
if_treatment_fees_check_division,
advenced_amount AS sum_init_amount ,
if_treatment_fees_check_division + advenced_amount AS test,
row_count AS "count"
FROM
(
SELECT
SUM(treatment_fees_difference) as if_treatment_fees_check_division,
count(*) as row_count,
chart_num
FROM hospital_payment_data
WHERE treatment_fees_check_division = 'test'
GROUP BY chart_num
) as TABLE1
LEFT OUTER JOIN advenced_payment AS TABLE2
ON TABLE1.chart_num = TABLE2.chart_num

SQL query top 2 columns of joined table?

I am having no luck attempting to get the top (x number) of rows from a joined table. I want the top 2 resources (ordered by name) which in this case should be Katie and Simon and regardless of what I've tried, I can't seem to get it right. You can see below what I've commented out - and what looks like it should work (but doesn't). I cannot use a union. Any ideas?
select distinct
RTRESOURCE.RNAME as Resource,
RTTASK.TASK as taskname, SUM(distinct SOTRAN.QTY2BILL) AS quantitytobill from SOTRAN AS SOTRAN INNER JOIN RTTASK AS RTTASK ON sotran.taskid = rttask.taskid
left outer JOIN RTRESOURCE AS RTRESOURCE ON rtresource.keyno=sotran.resid
WHERE sotran.phantom<>'y' and sotran.pgroup = 'L' and sotran.timesheet = 'y' and sotran.taskid >0 AND RTRESOURCE.KEYNO in ('193','159','200') AND ( SOTRAN.ADDDATE>='8/15/2015 12:00:00 AM' AND SOTRAN.ADDDATE<'9/3/2015 11:59:59 PM' )
//and RTRESOURCE.RNAME in ( select distinct top 2 RTRESOURCE.RNAME from RTRESOURCE order by RTRESOURCE.RNAME)
//and ( select count(*) from RTRESOURCE RTRESOURCE2 where RTRESOURCE2.RNAME = RTRESOURCE.RNAME ) <= 2
GROUP BY RTRESOURCE.rname,RTTASK.task,RTTASK.taskid,RTTASK.mdsstring ORDER BY Resource,taskname
You should provide a schema.
But lets assume your query work. You create a CTE.
WITH youQuery as (
SELECT *
FROM < you big join query>
), maxBill as (
SELECT Resource, Max(quantitytobill) as Bill
FROM yourQuery
)
SELECT top 2 *
FROM maxBill
ORDER BY Bill
IF you want top 2 alphabetical
WITH youQuery as (
SELECT *
FROM < you big join query>
), Names as (
SELECT distinct Resource
FROM yourQuery
Order by Resource
)
SELECT top 2 *
FROM Names

SP: Get 5 random records plus 1

I need to get 5 random records from a table plus a further record based on data from the users preferences as stored in a second table.
Here are the two statements i have created so far:
Gets favourite charity based on key set in TBL_MEMBERS:
SELECT DISTINCT TBL_CHARITIES.* FROM TBL_CHARITIES JOIN TBL_MEMBERS ON TBL_CHARITIES.cha_Key = TBL_MEMBERS.members_Favourite WHERE TBL_MEMBERS.members_Id = 16
Gets 5 random charities:
SELECT TOP 5 * FROM TBL_CHARITIES WHERE cha_Active = 'TRUE' AND cha_Key != '1' ORDER BY NEWID();
When used in a stored procedure it only returns the first SELECT statement to my .Net page. How can i combine the two statements whilst ensuring that no results are repeated (Eg the favourite is not present in the 5 random records?
Many Thanks!
Ok! So now ive updated things and got the following:
CREATE PROCEDURE web.getRandomCharities ( #tmp_ID bigint --members ID ) AS BEGIN
WITH q AS
(
SELECT TOP 5 *
FROM TBL_CHARITIES
WHERE cha_Active = 'TRUE'
AND cha_Key != '1'
ORDER BY NEWID()
)
SELECT * FROM q
UNION ALL
SELECT TOP 1 * FROM (
SELECT * FROM TBL_CHARITIES WHERE TBL_CHARITIES.cha_Key IN
( SELECT members_Favourite FROM TBL_MEMBERS WHERE members_Id = #tmp_ID ) EXCEPT SELECT * FROM q ) tc
END
Now i need to be able to the record "cha_Key == '1'" but only if its not the users favourite. Is this possible?
Thanks for everything so far. ITs truly appreciated.
Just UNION ALL them:
WITH q AS
(
SELECT TOP 5 *
FROM TBL_CHARITIES
WHERE cha_Active = 'TRUE'
AND cha_Key != '1'
ORDER BY NEWID()
)
SELECT *
FROM q
UNION ALL
SELECT TOP 1 *
FROM (
SELECT *
FROM TBL_CHARITIES
WHERE TBL_CHARITIES.cha_Key IN
(
SELECT members_Favourite
FROM TBL_MEMBERS
WHERE members_Id = 16
)
EXCEPT
SELECT *
FROM q
) tc
Update:
Unfortunately, the query above will not work as intended, since CTE's are reevaluated in SQL Server, and the second instance of q will give different records.
See this post in my blog for more detail:
SQL Server: random records avoiding CTE reevaluation
You need to rewrite the query as this:
WITH q AS
(
SELECT TOP 5 *
FROM TBL_CHARITIES
WHERE cha_Active = 'TRUE'
AND cha_Key != '1'
ORDER BY
NEWID()
),
r AS
(
SELECT *
FROM TBL_CHARITIES
WHERE TBL_CHARITIES.cha_Key IN
(
SELECT members_Favourite
FROM TBL_MEMBERS
WHERE members_Id = 16
)
)
SELECT TOP 6 *
FROM q
FULL OUTER JOIN
r
JOIN TBL_CHARITIES t
ON t.id = COALESCE(q.id, r.id)
ORDER BY
q.id
, assuming that id is the PRIMARY KEY of TBL_CHARITIES.
I would suggest pulling down a list of IDs to your .Net page and use your background code to randomly select N number of IDs and pass that as a parameter to your query. You can exclude the user's favorite by using where id != BL_MEMBERS.members_Favourite in the query which retrieves the existing IDs,.
This allows you to increase/decrease the number of randomly selected items fairly easily and moves the random generation and checks for unique items to .Net where it is accomplished much more easily.
try this
SELECT *
FROM (
SELECT TOP 5 *
FROM TBL_CHARITIES
WHERE cha_Active = 'TRUE'
AND cha_Key != '1'
AND cha_Key not in(SELECT TBL_MEMBERS.members_Favourite
WHERE TBL_MEMBERS.members_Id = 16)
ORDER BY NEWID()
) q
UNION ALL
SELECT TOP 1 TBL_CHARITIES.*
FROM TBL_CHARITIES
WHERE TBL_CHARITIES.cha_Key IN
(
SELECT TBL_MEMBERS.members_Favourite
FROM TBL_MEMBERS
WHERE TBL_MEMBERS.members_Id = 16
)
Create a Stored Procedure with a parameter #Memeber_ID.
Then do the type of code that Quassnoi said with a some modifications.
So, pull the top 5 records, but add a join to TBL_MEMBERS and where clause that the records pulled can't be that's memeber_ID's selection. Then do a UNION to that members selection.