I want to merge date and amount into a string - sql-server-2008

I am using the query which merges date column and amount column into a string, but as we are querying it by policy number, it is getting many rows, my thing is to merge these different values of the columns to one.
example:
2014/09/01 733.00
2012/08/01 322.02
so these are the different rows for one policy number, now I want them to be also in one single string as :
2014/09/01 733.00 2012/08/01 322.02
If they are two rows, then also the value of my column should merge all the values of dates and amounts into single string for that particular policy number.
The query I am using is :
SELECT
LEFT(CONVERT(VARCHAR, BSD.BILL_SCH_DTL_BILL_DT, 111), 10)
+ ' '+ CONVERT (VARCHAR(50),BSD.BILL_SCH_DTL_DRV_AMT ,128)Schedule_pymts, *
From POLICY_PERIOD_BILLING_SCHEDULE PB
JOIN BILLING_SCHEDULE_DETAIL BSD
ON BSD.PLCY_PRD_BILL_SCH_ID = PB.PLCY_PRD_BILL_SCH_ID
AND BSD.BILL_SCH_DTL_DRV_AMT <> 0
AND BSD.VOID_IND = 'n'
but this only merges one month and one amount together, but I need all the months of amount to be in one string(column) for that particular policy number.

You need to use FOR XML PATH to concatenate your rows to columns. I think something like this will work:
SELECT PB.*,
RTRIM((SELECT CONVERT(VARCHAR(10), BSD.BILL_SCH_DTL_BILL_DT, 111)+ ' '
+ CONVERT(VARCHAR(50), BSD.BILL_SCH_DTL_DRV_AMT, 128) + ' '
FROM BILLING_SCHEDULE_DETAIL AS BSD
WHERE BSD.PLCY_PRD_BILL_SCH_ID = PB.PLCY_PRD_BILL_SCH_ID
AND BSD.BILL_SCH_DTL_DRV_AMT <> 0
AND BSD.VOID_IND = 'n'
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')) AS Schedule_pymts
FROM POLICY_PERIOD_BILLING_SCHEDULE AS PB;
N.B. Don't use SELECT * - explicitly list your columns, but I don't know what they are so can't above

Related

Compare two Alphanumerical mysql columns (Find postcode district between range)

I have a mysql database that contains a range of postcode district ranges.
I am trying to find the row that matches the given district, in this example 'SY18'.
I have mysql query below, but it returns both the values in the table because the fields are alphanumeric.
SELECT rate FROM table WHERE district_from <= 'SY18' AND district_to >= 'SY18'
Table example
id district_from district_to rate
1 SY1 SY9 10
2 SY16 SY22 20
3 AL1 AL99 37
4 B1 B99 37
5 BB1 BB99 37
6 CB1 CB99 40
How do I return only correct results?
You can use SUBSTR to skip first characters of the string and then +0 to consider the value as a number. Example:
SELECT v
FROM
(SELECT 'SY1' v UNION SELECT 'SY16') t
WHERE SUBSTR(t.v, 3)+0 > 10
;
CREATE FUNCTION normalize_district (district VARCHAR(4))
RETURNS VARCHAR(4) DETERMINISTIC
RETURN CONCAT( TRIM(TRAILING CASE WHEN 0 + RIGHT(district, 2) > 0
THEN RIGHT(district, 2)
ELSE RIGHT(district, 1) END FROM district),
LPAD(CASE WHEN 0 + RIGHT(district, 2) > 0
THEN 0 + RIGHT(district, 2)
ELSE 0 + RIGHT(district, 1) END, 2, '0') );
and then
SELECT *
FROM district_to_test
LEFT JOIN rate ON normalize_district(district_to_test.district)
BETWEEN normalize_district(district_from)
AND normalize_district(district_to);
fiddle
0 + RIGHT(district, 2) > 0 in the function thecks does the last 2 symbols in district are digits.
If true then 2-digit number wil be extracted by RIGHT(), and the whole expression value will be above zero (you claim that there is no values like 'AA0' or 'AA00').
If false, and only one digit is present, then RIGHT() will give a substring which is started from a letter, and the value will be zero.
Based on this I divide the whole value to a prefix and numeric postfix, and add a zero to the numeric part making it 2-digit unconditionally. Such value can be used for direct string comparing by BETWEEN operator.
The goal of a function is to convert the value to 'AA00' format. For this purposes we must divide the whole value to textual and numeric parts and normalize (zero-pad) the latter one.
You may use any other dividing method. For example, you may check does the value contains two digits using LIKE '%\\d\\d'. Or backward, you may determine does the value contains two letters using LIKE '\\D\\D%'... these methods have relatively equal difficulty.

SQL Is there a way to link two tables with the same value but different formats?

So I have two columns from two different databases that I would like to link.
Problem is that my first column outputs the numbers with this format "1 789 987" and my second column outputs the data "0000000001789987"
How can I write my WHERE sql forumla to idententify these as matching?
Ok so I pulled out the qrys to excel to provide you with more information.
Here are the different tables.
Looks like Tbl2 has NUM column set to text. And even though the QRY in the program gave spaces to the numbers in Tbl1 it looks like the qry removed them shrug
SELECT *
FROM "Tbl1","Tbl2"
WHERE "Tbl1"."num" = "Tbl2"."num"
AND "Tbl1"."Date" BETWEEN '2019-01-21' AND '2019-01-25'
I hope the information became abit clearer. I'm new to SQL and Stackoverflow, i'll try and improve my questions information in the future.
Well, to transform format 1 to format 2 you can try something like this :
set #format1 = "1 789 987";
set #format2 = "0000000001789987";
select LPAD(REPLACE(#format1, ' ', ''), 16, "0") as format1, #format2 as format2
Output is :
====================================
format1 | format2
====================================
0000000001789987 | 0000000001789987
This way format1 looks like format2 if you test it. The REPLACE remove the ' ' and the LPAD will fill the string with 0 untill the string is 16 char length like the format2.
So you can use this in you WHERE condition :
...WHERE LPAD(REPLACE(your_first_column, ' ', ''), 16, "0") = your_other_column
Now you can try to transform both column in int too, you didn't provide lot of information about those format so hard to find the best solution !
This cast may fit for you:
NOTE: tbl1 contains ids like: 1 789 987
select *
from tbl1 join tbl2 on (
cast( -- casts to integer
replace(tbl1.text_id, ' ', '') -- removes whitespaces
as int) =
tbl2.numeric_id -- join on second table
)
In any case please provide sample data and a testable example what you did and the results you need

sql new column by delimiter with order ID

Hi this maybe a simple one but I need help specifically for MYsql
I have the data in one column lets call the column WORK 1,2,3,5,2 (these values are sometimes longer and shorter or more values are present e.g 12,15,11,15,16,143)
I need these to be put into 1 new column for each delimiter and have an ID for the order presented. e.g output
SELECT
*
FROM (SELECT
ROW_NUMBER()
OVER (ORDER BY WORK) AS Row,
RIGHT(LEFT(T.WORK, Number - 1),
CHARINDEX(',', REVERSE(LEFT(',' + T.WORK, Number - 1)))) AS a
FROM master..spt_values,
<YOUR_TABLENAME> T
WHERE Type = 'P'
AND Number BETWEEN 1 AND LEN(T.WORK) + 1
AND (SUBSTRING(T.WORK, Number, 1) = ','
OR SUBSTRING(T.WORK, Number, 1) = '')) AS A

Counting comma separated values in TSQL

SCHEMA / DATA for TABLE :
SubscriberId NewsletterIdCsv
------------ ---------------
11 52,52,,52
We have this denormalized data, where I need to count the number of comma separated values, for which I am doing this :
SELECT SUM(len(newsletteridcsv) - len(replace(rtrim(ltrim(newsletteridcsv)), ',','')) +1) as SubscribersSubscribedtoNewsletterCount
FROM TABLE
WHERE subscriberid = 11
Result :
SubscribersSubscribedtoNewsletterCount
--------------------------------------
4
The problem is some of our data has blanks / spaces in between the comma separated values, if I run the above query the expected result should be 3 (as one of the value is blank space), how do I check in my query to exclude the blank spaces?
EDIT :
DATA :
SubscriberId NewsletterIdCsv
------------ ---------------
11 52,52,,52
12 22,23
I need to get an accumulative SUM instead of just each rows sum, so for this above data I need to have just a final count i.e. 5 in this case, excluding the blank space.
Here's one solution, although their may be a more efficient way:
SELECT A.[SubscriberId],
SUM(CASE WHEN Split.a.value('.', 'VARCHAR(100)') = '' THEN 0 ELSE 1 END) cnt
FROM
(
SELECT [SubscriberId],
CAST ('<M>' + REPLACE(NewsletterIdCsv, ',', '</M><M>') + '</M>' AS XML) AS String
FROM YourTable
) AS A
CROSS APPLY String.nodes ('/M') AS Split(a)
GROUP BY A.[SubscriberId]
And the SQL Fiddle.
Basically it converts your NewsletterIdCsv field to XML and then uses CROSS APPLY to split the data. Finally, using CASE to see if it's blank and SUM the non-blank values. Alternatively, you could probably build a UDF to do something similar.

Select data which have same letters

I'm having trouble with this SQL:
$sql = mysql_query("SELECT $menucompare ,
(COUNT($menucompare ) * 100 / (SELECT COUNT( $menucompare )
FROM data WHERE $ww = $button )) AS percentday FROM data WHERE $ww >0 ");
$menucompare is table fields names what ever field is selected and contains data bellow
$button is the week number selected (lets say week '6')
$ww table field name with row who have the number of week '6'
For example, I have data in $menucompare like that:
123456bool
521478bool
122555heel
147788itoo
and I want to select those, who have same word in the last of the data and make percentage.
The output should be like that:
bool -- 50% (2 entries)
heel -- 25% (1 entry)
itoo -- 25% (1 entry)
Any clearness to my SQL will be very appreciated.
I didn't find anything like that around.
Well, keeping data in such format probably not the best way, if possible, split the field into 2 separate ones.
First, you need to extract the string part from the end of the field.
if the length of the string / numeric parts is fixed, then it's quite easy;
if not, you should use regular expressions which, unfortunately, are not there by default with MySQL. There's a solution, check this question: How to do a regular expression replace in MySQL?
I'll assume, that numeric part is fixed:
SELECT s.str, CAST(count(s.str) AS decimal) / t.cnt * 100 AS pct
FROM (SELECT substr(entry, 7) AS str FROM data) AS s
JOIN (SELECT count(*) AS cnt FROM data) AS t ON 1=1
GROUP BY s.str, t.cnt;
If you'll have regexp_replace function, then substr(entry, 7) should be replaced to regexp_replace(entry, '^[0-9]*', '') to achieve the required result.
Variant with substr can be tested here.
When sorting out problems like this, I would do it in two steps:
Sort out the SQL independently of the presentation language (PHP?).
Sort out the parameterization of the query and the presentation of the results after you know you've got the correct query.
Since this question is tagged 'SQL', I'm only going to address the first question.
The first step is to unclutter the query:
SELECT menucompare,
(COUNT(menucompare) * 100 / (SELECT COUNT(menucompare) FROM data WHERE ww = 6))
AS percentday
FROM data
WHERE ww > 0;
This removes the $ signs from most of the variable bits, and substitutes 6 for the button value. That makes it a bit easier to understand.
Your desired output seems to need the last four characters of the string held in menucompare for grouping and counting purposes.
The data to be aggregated would be selected by:
SELECT SUBSTR(MenuCompare, -4) AS Last4
FROM Data
WHERE ww = 6
The divisor in the percentage is the count of such rows, but the sub-stringing isn't necessary to count them, so we can write:
SELECT COUNT(*) FROM Data WHERE ww = 6
This is exactly what you have anyway.
The divdend in the percentage will be the group count of each substring.
SELECT Last4, COUNT(Last4) * 100.0 / (SELECT COUNT(*) FROM Data WHERE ww = 6)
FROM (SELECT SUBSTR(MenuCompare, -4) AS Last4
FROM Data
WHERE ww = 6
) AS Week6
GROUP BY Last4
ORDER BY Last4;
When you've demonstrated that this works, you can re-parameterize the query and deal with the presentation of the results.