I have a crystal report connected to a table with a command which has parameters, this command query is working
SELECT
date1,
car_num,
ar_dromologiou,
Sum(kilomtres) As ksum,
sum(posostita_ltitra) as sumpos,
sum(shmaia) as sumkom,
sum(sinokomsim) AS x3
FROM
Table_1
WHERE
date1 BETWEEN {?d1} AND {?d2}
GROUP BY
date1,
car_num,
ar_dromologiou;
this doesn't work
SELECT
date1,
car_num,
ar_dromologiou,
Sum(kilomtres) As ksum,
sum(posostita_ltitra) as sumpos,
sum(shmaia) as sumkom,
sum(sinokomsim) AS x3
FROM
Table_1
WHERE
car_num LIKE {?c1} AND
date1 BETWEEN {?d1} AND {?d2}
GROUP BY
date1,
car_num,
ar_dromologiou;
Where is the fault?
Thank you all for the answers , I found that the values where in non english characters and crystal Reports wants some Extra configuration for this, didn't find yet but when I insert a record with english characters and in the parameter input english chars it showed the record, so something about the character encoding.
The problem seems to be in your where clause where you compare car_num.
If you pass in your parameter {?c1} and it doesn't include any wildcard charaters like % or _ you will only get exact matches.
Use wildcard characters appropriate for your use case, e.g.
WHERE
car_num LIKE {?c1} + '%' AND
date1 BETWEEN {?d1} AND {?d2}
This will match all rows where car_num starts with the value of your parameter {?c1}.
You may want to have a look at the documentation for the LIKE operator.
Related
SELECT value from table1 limit 3;
When I run the above query, I'm getting the below results:
;12770258;;;;103=::dupe::0|112=::dupe::0|114=search-results#product-id#Lettuce#not-recommended#r02#s01
;12880258;;;;103=::dupe::0|112=::dupe::0|114=search-results#product-id#Lettuce#not-recommended#r02#s01
;12990258;;;;103=::dupe::0|112=::dupe::0|114=search-results#product-id#Lettuce#not-recommended#r02#s01
I want the results to be displayed as below:
12770258
12880258
12990258
How to implement this using Regular Expression? Kindly guide.
We can use REGEXP_SUBSTR here:
SELECT REGEXP_SUBSTR(value, '\\d+', 1, 1, 'i', 1) AS output
FROM yourTable;
The above call to REGEXP_SUBSTR finds the first digit in the column, starting the search at the start of the column. In regex, \d+ matches a group of one or more digit characters.
you could just use SPLIT if you know it's always the "second" value in the series. If that is not true, then the REGEPX version will not help you ether.
SELECT ';12770258;;;;103=::dupe::0|112=::dupe::0|114=search-results#product-id#Lettuce#not-recommended#r02#s01' as col1
,split(col1,';')[1]::text;
COL1
SPLIT(COL1,';')[1]::TEXT
;12770258;;;;103=::dupe::0|112=::dupe::0|114=search-results#product-id#Lettuce#not-recommended#r02#s01
12770258
I am new to SQL and it seems not to be the same as tradition coding. Anyways, I am trying to figure out why my results end up empty but only with the first AND statement. If I remove this statement, the code works. The syntax seems correct. What I am trying to do is match channel names with 'P' and 'HDP' at the end of the columns and not match channel numbers. Maybe I am wrong on the syntax. Any help on this matter would be appreciated. Also, I am using Microsoft SQL Server Management Studio 2012.
How the results should look:
SELECT a.ChannelNumber AS "Standard Channel",
a.DisplayName AS "Standard Name",
b.ChannelNumber AS "HD Channel",
b.DisplayName AS "HD Name"
FROM CHANNEL a CROSS JOIN CHANNEL b
WHERE b.ChannelNumber <> a.ChannelNumber
AND b.DisplayName = a.DisplayName /*this is what is giving me problems*/
AND RIGHT(b.DisplayName, 3) LIKE '%HDP'
AND RIGHT(a.DisplayName, 1) LIKE '%P';
Ultimately you want things like AETVP and AETVHDP to be "equal". This doesn't seem like a use case for a Cross Join. You can break this down with a CTE.
First you'll define your HD channels, then your Standard Channels. In each of those blocks you can get the core part of the channel's name (the part without the P or HDP). Then join those together on the CoreName. This will enable us to join AETV to AETV
WITH HdChannels
AS (
SELECT *
,CoreName = left(DisplayName, len(DisplayName) - len('HDP'))
FROM Channel
WHERE displayName LIKE '%HDP'
)
,StdChannels
AS (
SELECT *
,CoreName = left(DisplayName, len(DisplayName) - len('P'))
FROM Channel
WHERE displayName LIKE '%P'
AND displayName NOT LIKE '%HDP'
)
SELECT std.ChannelNumber AS [Standard Channel]
,std.DisplayName AS [Standard Name]
,hd.ChannelNumber AS [HD Channel]
,hd.DisplayName AS [HD Name]
FROM HdChannels hd
INNER JOIN StdChannels std ON std.CoreName = hd.CoreName
To answer your question,
"Give reasons as to why my AND clause returns an empty string in SQL"
it's because you've declared a.DisplayName = b.DisplayName in the WHERE. And that can't be the case according to the picture of the output you've linked to because the Display names are spelled differently.
The only difference between standard and HD tables is HD tables end with "HDP". Standard tables never end with "HDP", though they do end with a "P".
In the absence of sample data, I've included the most basic example I could think of using a temp table.
DECLARE #CHANNEL TABLE(ChannelNumber int, DisplayName varchar(100))
INSERT INTO #CHANNEL VALUES
(3, 'ABCP'), (25, 'ABCHDP')
SELECT a.ChannelNumber AS "Standard Channel",
a.DisplayName AS "Standard Name",
b.ChannelNumber AS "HD Channel",
b.DisplayName AS "HD Name"
FROM #CHANNEL a CROSS JOIN #CHANNEL b
WHERE LEFT(a.DisplayName, LEN(a.DisplayName) - 1) + 'HDP' = b.DisplayName
AND a.DisplayName NOT LIKE '%HDP'
AND b.DisplayName LIKE '%HDP'
AND a.ChannelNumber <> b.ChannelNumber
Produces output:
Standard Channel Standard Name HD Channel HD Name
3 ABCP 25 ABCHDP
The algorithm identifies standard channels (NOT LIKE '%HDP') and HD channels (LIKE '%HDP') on the left and right sides of the CROSS JOIN.
Notice in your code you put: AND RIGHT(b.DisplayName, 3) LIKE '%HDP'... it is unnecessary to specify the RIGHT function with a length of chars- when you indicate the end of the string using LIKE '%HDP'.
LEFT(a.DisplayName, LEN(a.DisplayName) - 1) + 'HDP' cuts off the last char of the Standard Channel's DisplayName (which is always a 'P' by it's naming convention) and concatenates 'HDP' at the end of the result. This is compared to the format for HD channels which always end with 'HDP'.
When the conditions match you get a row of data.
Looking at the filtering conditions- you can see that a.DisplayName can never equal b.DisplayName
The Problem
I have a number of filename strings that I want to parse into columns using a tilda as delimiter. The strings take on the static format:
Filepath example C:\My Documents\PDF
Surname example Walker
First Name example Thomas
Birth Date example 19991226
Document Created Datetime example 20180416150322
Document Extension example .pdf
So a full concatenated example would be something like:
C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf
I want to ignore the file path and extension given in the string and only parse the following values into columns:
Surname, First Name, Birth Date, Document Created Datetime
So something like:
SELECT Surname = --delimitedString[0]
FirstName = --delimitedString[1]
--etc.
What I have tried
I know that I have several tasks I would need to perform in order to split the string, first I would need to trim off the extension and file path so that I can return a string delimited by tildas (~).
This is problem one for me, however problem 2 is splitting the new delimted string itself i.e.
Walker~Thomas~19991226~20180416150322
Ive had a good read through this very comprehensive question and It seems (as im using SQL Server 2008R2) the only options are to use either a function with loops or recursive CTE's or attempt a very messy attempt using SUBSTRING() with charIndex().
Im aware that If I had access to SQL Server 2016 I could use string_split but unfortunately I cant upgrade.
I do have access to SSIS but im very new to it so decided to attempt the bulk of the work within a SQL statement
Here is a way without a splitter that shouldn't be too complicated...
declare #var table (filepath varchar(256))
insert into #var values
('C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf')
;with string as(
select
x = right(filepath,charindex('\',reverse(filepath))-1)
from #var
)
select
SurName= substring(x,1,charindex('~',x) - 1)
,FirstName = substring(x,charindex('~',x) + 1,charindex('~',x) - 1)
from string
I know you mentioned wanting to avoid the charindex() option if at all possible, but I worked it out in a hopefully semi-readable way. I find it somewhat easy to read complex functions like this when I space each parameter on a different line and use indent levels. It's not the most proper looking, but it helps with legibility:
with string as (select 'C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf' as filepath)
select
substring(
filepath,
len(filepath)-charindex('\',reverse(filepath))+2, --start location, after last '\'
len(filepath)- --length of path
(len(filepath)-charindex('\',reverse(filepath))+2)- --less characters up to last '\'
(len(filepath)-charindex('.',filepath)) --less file extention
)
from string
Fritz already have a great start, my answer just add on top it
with string as (select 'C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf' as filepath)
, newstr as (
select
REPLACE(substring(
filepath,
len(filepath)-charindex('\',reverse(filepath))+2, --start location, after last '\'
len(filepath)- --length of path
(len(filepath)-charindex('\',reverse(filepath))+2)- --less characters up to last '\'
(len(filepath)-charindex('.',filepath)) --less file extention
) , '~', '.') as new_part
from string
)
SELECT
PARSENAME(new_part,4) as Surname,
PARSENAME(new_part,3) as [First Name],
PARSENAME(new_part,2) as [Birth Date],
PARSENAME(new_part,1) as [Document Created Datetime]
FROM newstr
I have a requirement to pull data in a specific format and I'm struggling slightly with the ROWTOCOL function and was hoping a fresh pair of eyes might be able to help.
I'm using 10g Oracle DB (10.2) so LISTAGG which appears to do what I need to achieve is not an option.
I need to aggregate a number of usernames into a string delimited with a '$' but I also need to concatenate another column to to build up email addresses.
select
rowtocol('select username_id from username where user_id = '||s.user_id|| 'order by USERNAME_ID asc','#'||d.domain_name||'$')
from username s, domain d
where s.user_id = d.user_id
(I've simplified the query specific to just this function as the actual query is quite large and all works except for this particular function.)
in the DOMAIN Table I have a number of domains such as 'hotmail.com','gmail.com' etc
I need to concatenate the username, an '#' symbol followed by the domain and all delimited with a '$'
such as ......
joe.bloggs#gmail.com$joeblogs#gmail.com$joe_bloggs#gmail.com
I've battled with this and I've got close but in reverse?!.....
gmail.com$joe.bloggs#gmail.com$joeblogs#gmail.com$joe_bloggs
I've also noticed that if I play around with the delimiter (,'#'||d.domain_name||'$') it has a tendency to drop off the first character as can be seen above the preceding '#' has been dropped from the first email address.
Can anyone offer any suggestions as to how to get this working?
Many Thanks in advance!
Assuming you're using the rowtocol function from OTN, and have tables something like:
create table username (user_id number, username_id varchar2(20));
create table domain (user_id number, domain_name varchar2(20));
insert into username values (1, 'joe.bloggs');
insert into username values (1, 'joebloggs');
insert into username values (1, 'joe_bloggs');
insert into domain values (1, 'gmail.com');
Then your original query gets three rows back:
gmail.com$joe.bloggs
gmail.com$joe_bloggs#gmail.com$joebloggs
gmail.com$joe_bloggs#gmail.com$joebloggs
You're passing the data from each of your user IDs to a separate call to rowtocol, which isn't really what you want. You can get the result I think you're after by reversing it; pass the main query that joins the two tables as the select argument to the function, and have that passed query do the username/domain concatenation - that is a separate step to the string aggregation:
select
rowtocol('select s.username_id || ''#'' || d.domain_name from username s join domain d on d.user_id = s.user_id', '$')
from dual;
which gets a single result:
joe.bloggs#gmail.com$joe_bloggs#gmail.com$joebloggs#gmail.com
Whether that fits into your larger query, which you haven't shown, is a separate question. You might need to correlate it with the rest of your query.
There are other ways to string aggregation in Oracle, but this function is one way, and you already have it installed. I'd look at alternatives though, such as ThomasG's answer, which make it a bit clearer what's going on I think.
As Alex told you in comments, this ROWTOCOL isn't a standard function so if you don't show its code, there's nothing we can do to fix it.
However you can accomplish what you want in Oracle 10 using the XMLAGG built-in function.
try this :
SELECT
rtrim (xmlagg (xmlelement (e, s.user_id || '#' || d.domain_name || '$')).extract ('//text()'), '$') whatever
FROM username s
INNER JOIN domain d ON s.user_id = d.user_id
I have string data in the following format:
MODELNUMBER=Z12345&HELLOWORLD=WY554&GADTYPE=PLA&ID=Z-12345
/DTYPE=PLA&ID=S-10758&UN_JTT_REDIRECT=UN_JTT_IOSV
and need to extract IDs based on two conditions
Starting after a pattern &ID=
Ending till the last character or
if it hits a & stop right there.
So in the above example I'm using the following code:
SUBSTRING(MyCol,(PATINDEX('%&id=%',[MyCol])+4),(LEN(MyCol) - PATINDEX('%&id%',[MyCol])))
Essentially looking the pattern &id=% and extract string after that till end of the line. Would anyone advise on how to handle the later part of the logic ..
My current results are
Z-12345
Z-12345&UN_JTT_REDIRECT=UN_JTT_IOSV
What I need is
Z-12345
Z-12345
Try this
SUBSTRING(MyCol, (PATINDEX('%[A-Z]-[0-9][0-9][0-9][0-9][0-9]%',[MyCol])),7)
if you run into performance issues add the where clause below
-- from Mytable
WHERE [MyCol] like '%[A-Z]-[0-9][0-9][0-9][0-9][0-9]%'
maybe not the most elegant solution but it works for me.
Correct syntax of PATINDEX
Here's one example how to do it:
select
substring(d.data, s.s, isnull(nullif(e.e,0),2000)-s.s) as ID,
d.data
from data d
cross apply (
select charindex('&ID=', d.data)+4 as s
) s
cross apply (
select charindex('&', d.data, s) as e
) e
where s.s > 4
This assumes there data column is varchar(2000) and the where clause leaves out any rows that don't have &ID=
The first cross apply searches for the start position, the second one for the end. The isnull+nulliff in the actual select handles the case where & is not found and replaces it with 2000 to make sure the whole string is returned.