UFT retrieve data from SQL: Item cannot be found in the collection - sql

Using UFT12.51. Need to retrieve data from SQL Server.
Same question was asked by many people, but researching several posts, could not find any answer.
The query to run is:
DROP TABLE IF EXISTS dbo.TempTableOutgoing, TempTableOutgoingLeft, TempTableOutgoingRight;
SELECT Table1.RowNum, Table1.present, Table2.Amount INTO TempTableOutgoingLeft FROM
(Select cte.* FROM (VALUES ('1','1st Present'), ('2','1P 1-Sided'), ('3','')
) as cte (RowNum,present)) AS Table1
LEFT OUTER JOIN (SELECT ca.* FROM [eBalance].[dbo].[TRANS_DISTRIB] AS t1
CROSS APPLY (Values
('1', CONVERT(VARCHAR, FirstPresent)),
('2', CONVERT(VARCHAR, FirstPresentOneSided)),
('3',NULL)
) AS ca (RowNum, Amount)
WHERE t1.FileDate = ''"&FileDate&"'' AND t1.CardType = 'AMEX') as Table2
on Table1.RowNum = Table2.RowNum;
SELECT * INTO TempTableOutgoingRight FROM(
SELECT vi.rownumber, vi.outgoing, vi.oamount FROM [eBalance].[dbo].[AMEX_OUTGOING] AS V1
CROSS APPLY (Values ('1','Sales', Sales),
('2','Cash Advances', CashAdvances),
('3','Returns', Credits)
) as vi (rownumber, outgoing, oamount)
WHERE v1.FileDate = ''"&FileDate&"'')R;
SELECT RowNum, Present, Amount, Outgoing, OAmount INTO TempTableOutgoing FROM(
SELECT * FROM(SELECT * FROM TempTableOutgoingLeft
UNION ALL
SELECT '4','Total', CONVERT(VARCHAR, SUM(CAST(ISNULL(Amount,'0') AS decimal(15,2)))) from TempTableOutgoingLeft) AS Table1
LEFT OUTER JOIN (SELECT * FROM TempTableOutgoingRight
UNION ALL
SELECT '4','Outgoing Settlement Total', CONVERT(VARCHAR, SUM(CAST(ISNULL(oamount,'0') AS decimal(15,2)))) from TempTableOutgoingRight) AS Table2
ON Table1.RowNum = Table2.rownumber) Z;
DROP TABLE TempTableOutgoingLeft;
DROP TABLE TempTableOutgoingRight;
SELECT present, Amount, Outgoing, OAmount, Variance FROM(
SELECT * FROM dbo.TempTableOutgoing z1
INNER JOIN (Select RowN, Variance from (
SELECT DISTINCT RowN, Variance FROM TempTableOutgoing AS TTO
CROSS APPLY (Values
('1',''),('2', (SELECT CONVERT(VARCHAR, SUM(CAST(ISNULL(Amount,'0') AS decimal(15,2)))-SUM(CAST(ISNULL(OAmount,'0') AS decimal(15,2))))
FROM TempTableOutgoing where RowNum IN (1,2,3))), ('3',''))
as z (RowN,Variance) where TTO.RowNum IN (1,2,3)
UNION ALL
SELECT DISTINCT z.* FROM TempTableOutgoing AS TTO
CROSS APPLY (Values
('4', (SELECT CONVERT(VARCHAR, SUM(CAST(ISNULL(Amount,'0') AS decimal(15,2)))-SUM(CAST(ISNULL(OAmount,'0') AS decimal(15,2))))
FROM TempTableOutgoing where RowNum IN (4)))
) as z (RowN,Variance) where TTO.RowNum IN (4)
) V Group by RowN, Variance) V1
on z1.RowNum = V1.RowN) T;
When running in SQL Management Studio, it works well and gives proper result:
present |Amount |Outgoing |OAmount |Variance
============+===========+=========================+===========+========
1st Present |5028510.18 |Sales |5110968.89
------------+-----------+-------------------------+-----------+--------
1P 1-Sided |0.00 |Cash Advances |0.00 |0.00
------------+-----------+-------------------------+-----------+--------
|NULL |Returns |-82458.71 |
------------+-----------+-------------------------+-----------+--------
Total |5028510.18 |Outgoing Settlement Total|5028510.18 |0.00
But when UFT runs the query, it returns error message while retrieving information:
print objRS.Fields(1)
Item cannot be found in the collection corresponding to the requested
name or ordinal
Printing err.number returns 0:
objConnection.Open "Provider=sqloledb.1; Server=server;User Id=userid; Password=password; Database=database"
Set objRS = objConnection.Execute(query)
print err.number
print objRS.state
print objConnection.state
0
0
0
The connection settings are 100% good, and even a simple query like SELECT * from [database].[schema].[table] and print recordset.fields(0) returns a valid result.
As far as I researched, problem might cause when the query has more than one column with same name, but that is not my case.
What can be the problem?

Related

Consolidate information (time serie) from two tables

MS SQL Server
I have two tables with different accounts from the same customer:
Table1:
ID
ACCOUNT
FROM
TO
1
A
01.10.2019
01.12.2019
1
A
01.02.2020
09.09.9999
and table2:
ID
ACCOUNT
FROM
TO
1
B
01.12.2019
01.01.2020
As result I want a table that summarize the story of this costumer and shows when he had an active account and when he doesn't.
Result:
ID
FROM
TO
ACTIV Y/N
1
01.10.2019
01.01.2020
Y
1
02.01.2020
31.01.2020
N
1
01.02.2020
09.09.9999
Y
Can someone help me with some ideas how to proceed?
This is the typical gaps and island problem, and it's not usually easy to solve.
You can achieve your goal using this query, I will explain it a little bit.
You can test on this db<>fiddle.
First of all... I have unified your two tables into one to simplify the query.
-- ##table1
select 1 as ID, 'A' as ACCOUNT, convert(date,'2019-10-01') as F, convert(date,'2019-12-01') as T into ##table1
union all
select 1 as ID, 'A' as ACCOUNT, convert(date,'2020-02-01') as F, convert(date,'9999-09-09') as T
-- ##table2
select 1 as ID, 'B' as ACCOUNT, convert(date,'2019-12-01') as F, convert(date,'2020-01-01') as T into ##table2
-- ##table3
select * into ##table3 from ##table1 union all select * from ##table2
You can then get your gaps and island using, for example, a query like this.
It combines recursive cte to generate a calendar (cte_cal) and lag and lead operations to get the previous/next record information to build the gaps.
with
cte_cal as (
select min(F) as D from ##table3
union all
select dateadd(day,1,D) from cte_cal where d < = '2021-01-01'
),
table4 as (
select t1.ID, t1.ACCOUNT, t1.F, isnull(t2.T, t1.T) as T, lag(t2.F, 1,null) over (order by t1.F) as SUP
from ##table3 t1
left join ##table3 t2
on t1.T=t2.F
)
select
ID,
case when T = D then F else D end as "FROM",
isnull(dateadd(day,-1,lead(D,1,null) over (order by D)),'9999-09-09') as "TO",
case when case when T = D then F else D end = F then 'Y' else 'N' end as "ACTIV Y/N"
from (
select *
from cte_cal c
cross apply (
select t.*
from table4 t
where t.SUP is null
and (
c.D = t or
c.D = dateadd(day,1,t.T)
)
) t
union all
select F, * from table4 where T = '9999-09-09'
) p
order by 1
option (maxrecursion 0)
Dates like '9999-09-09' must be treated like exceptions, otherwise I would have to create a calendar until that date, so the query would take long time to resolve.

Using Multiple CTE with one INSERT statement. [Error:More Columns than Specified in Column List]

I have CTE1 and CTE2 as below. The CTE2 shows error
CTE2 has more columns than specified in the column list
I would like to know what I am doing wrong. It cannot be because Insert statement has more columns than the CTE2 because CTE1 worked fine before. CTE1 and CTE2 are both using different tables. Is that the problem?
If I remove the parameters in CTE2(NewRoomCost,NewQuantity) Then I get the error
No Columns specified for Column3 of CTE2
Below is the code that I tried. Any help would be appreciated.
CREATE PROCEDURE dbo.SpTransactionGenerate
AS
BEGIN
SET NOCOUNT ON
DECLARE #MinReservationId INT = (SELECT MIN(f.ReservationId) FROM dbo.Reservation AS f)
DECLARE #MaxReservationId INT = (SELECT MAX(f.ReservationId) FROM dbo.Reservation AS f)
DECLARE #FirstSeasonEndDate DATE= '2018-02-13';
DECLARE #SecondSeasonEndDate DATE='2018-02-14';
DECLARE #ThirdSeasonEndDate DATE='2018-12-31';
WHILE #MinReservationId<=#MaxReservationId
BEGIN
WITH CTE1(ServiceId,ServiceRate,Quantity) AS
(
SELECT ServiceId,
ServiceRate,
ABS(CHECKSUM(NEWID())%3) + 1 AS Quantity
FROM dbo.[Service]
),
CTE2(NewRoomCost,NewQuantity) AS
(
SELECT
(SELECT roomRate.RoomCost FROM dbo.RoomRate as roomRate WHERE roomRate.RoomTypeId=
(SELECT room.RoomTypeId FROM dbo.Room as room
JOIN dbo.Reservation as res ON res.RoomId=room.RoomId WHERE res.ReservationId=#MinReservationId
AND roomRate.SeasonId=(
CASE WHEN (SELECT resv.CheckInDate FROM dbo.Reservation as resv WHERE resv.ReservationId=#MinReservationId)<=#FirstSeasonEndDate
THEN (SELECT sea.SeasonId FROM dbo.Season as sea WHERE sea.SeasonEndDate=#FirstSeasonEndDate)
WHEN (SELECT resv.CheckInDate FROM dbo.Reservation as resv WHERE resv.ReservationId=#MinReservationId)<=#SecondSeasonEndDate
THEN (SELECT sea.SeasonId FROM dbo.Season as sea WHERE sea.SeasonEndDate=#SecondSeasonEndDate)
ELSE (SELECT sea.SeasonId FROM dbo.Season as sea WHERE sea.SeasonEndDate=#ThirdSeasonEndDate) END
)
)) AS NewRoomCost,
DATEDIFF(DAY,(SELECT r.CheckinDate FROM dbo.Reservation AS r WHERE r.ReservationId=#MinReservationId), (SELECT r.CheckOutDate FROM dbo.Reservation AS r WHERE r.ReservationId=#MinReservationId)) AS NewQuantity,
)
INSERT INTO dbo.[Transaction]
(
ReservationId,
ServiceId,
Rate,
Quantity,
Amount
)
SELECT
#MinReservationId,
ServiceId,
ServiceRate,
Quantity,
ServiceRate*Quantity
FROM CTE1
UNION
SELECT
#MinReservationId,
NULL,
NewRoomCost,
NewQuantity,
NewRoomCost*NewQuantity
FROM CTE2
SELECT #MinReservationId=#MinReservationId+1
END
END
UPDATE : The error resulted because of a single extra comma in the CTE2. Sorry for the unnecessary question asked.
The issue in CTE2 is that you have an extra comma at the end of this line:
DATEDIFF(DAY,(SELECT r.CheckinDate FROM dbo.Reservation AS r WHERE r.ReservationId=#MinReservationId), (SELECT r.CheckOutDate FROM dbo.Reservation AS r WHERE r.ReservationId=#MinReservationId)) AS NewQuantity,
A sidenote: I suggest not writing explicit column names in the future but rather just naming them as you already did with the AS keyword. It just gives more flexibility overall.
Because your 2nd CTE defines two columns:
CTE2(NewRoomCost,NewQuantity) AS
But your select statement returns 3.
(SELECT roomRate.RoomCost FROM...
DATEDIFF(DAY,(SELECT r.CheckinDate...
(SELECT r.CheckOutDate FROM dbo.Reservation...

Syntax error in FROM clause - MS ACCESS

I am working with a tool that would extract some data from an Access Database. So basically, i am working on a query to get this data.
Below is the code i am currently working on.
I am getting an error: Syntax error in FROM clause
I can't seem to find where the query is going wrong. I would appreciate any help! Thank youu.
EDIT: putting my actual query
SELECT table_freq.*, IIF(table_freq.txn_ctr > (table_ave_freq.ave_freq * 3), "T", "F") as suspicious_flag
FROM
(
SELECT tbl_TransactionHistory.client_num, tbl_TransactionHistory.client_name,
tbl_TransactionHistory.transaction_date, Count(tbl_TransactionHistory.client_num) AS txn_ctr
FROM tbl_TransactionHistory
GROUP BY tbl_TransactionHistory.client_num, tbl_TransactionHistory.client_name,
tbl_TransactionHistory.transaction_date
) AS table_freq
INNER JOIN
(
SELECT table_total_freq.client_num, total_txn_ctr as TotalTransactionFrequency, total_no_days as TotalTransactionDays,
(table_total_freq.total_txn_ctr)/(table_no_of_days.total_no_days) AS ave_freq
FROM
(
(
SELECT client_num, SUM(txn_ctr) AS total_txn_ctr
FROM
(
SELECT client_num, client_name, transaction_date, COUNT(client_num) AS txn_ctr
FROM tbl_TransactionHistory
GROUP BY client_num, client_name, transaction_date
) AS tabFreq
GROUP BY client_num
) AS table_total_freq
INNER JOIN
(
SELECT client_num, COUNT(txn_date) as total_no_days
FROM
(
SELECT DISTINCT(transaction_date) as txn_date, client_num
FROM tbl_TransactionHistory
ORDER BY client_num
) AS table1
GROUP BY client_num
) AS table_no_of_days
ON table_total_freq.client_num = table_no_of_days.client_num
)
) AS table_ave_freq
ON table_freq.client_num = table_ave_freq.client_num

Get every combination of sort order and value of a csv

If I have a string with numbers separated by commas, like this:
Declare #string varchar(20) = '123,456,789'
And would like to return every possible combination + sort order of the values by doing this:
Select Combination FROM dbo.GetAllCombinations(#string)
Which would in result return this:
123
456
789
123,456
456,123
123,789
789,123
456,789
789,456
123,456,789
123,789,456
456,789,123
456,123,789
789,456,123
789,123,456
As you can see not only is every combination returned, but also each combination+sort order as well. The example shows only 3 values separated by commas, but should parse any amount--Recursive.
The logic needed would be somewhere in the realm of using a WITH CUBE statement, but the problem with using WITH CUBE (in a table structure instead of CSV of course), is that it won't shuffle the order of the values 123,456 456,123 etc., and will only provide each combination, which is only half of the battle.
Currently I have no idea what to try. If someone can provide some assistance it would be appreciated.
I use a User Defined Table-valued Function called split_delimiter that takes 2 values: the #delimited_string and the #delimiter_type.
CREATE FUNCTION [dbo].[split_delimiter](#delimited_string VARCHAR(8000), #delimiter_type CHAR(1))
RETURNS TABLE AS
RETURN
WITH cte10(num) AS
(
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
,cte100(num) AS
(
SELECT 1
FROM cte10 t1, cte10 t2
)
,cte10000(num) AS
(
SELECT 1
FROM cte100 t1, cte100 t2
)
,cte1(num) AS
(
SELECT TOP (ISNULL(DATALENGTH(#delimited_string),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM cte10000
)
,cte2(num) AS
(
SELECT 1
UNION ALL
SELECT t.num+1
FROM cte1 t
WHERE SUBSTRING(#delimited_string,t.num,1) = #delimiter_type
)
,cte3(num,[len]) AS
(
SELECT t.num
,ISNULL(NULLIF(CHARINDEX(#delimiter_type,#delimited_string,t.num),0)-t.num,8000)
FROM cte2 t
)
SELECT delimited_item_num = ROW_NUMBER() OVER(ORDER BY t.num)
,delimited_value = SUBSTRING(#delimited_string, t.num, t.[len])
FROM cte3 t;
Using that I was able to parse the CSV to a table and join it back to itself multiple times and use WITH ROLLUP to get the permutations you are looking for.
WITH Numbers as
(
SELECT delimited_value
FROM dbo.split_delimiter('123,456,789',',')
)
SELECT CAST(Nums1.delimited_value AS VARCHAR)
,ISNULL(CAST(Nums2.delimited_value AS VARCHAR),'')
,ISNULL(CAST(Nums3.delimited_value AS VARCHAR),'')
,CAST(Nums4.delimited_value AS VARCHAR)
FROM Numbers as Nums1
LEFT JOIN Numbers as Nums2
ON Nums2.delimited_value not in (Nums1.delimited_value)
LEFT JOIN Numbers as Nums3
ON Nums3.delimited_value not in (Nums1.delimited_value, Nums2.delimited_value)
LEFT JOIN Numbers as Nums4
ON Nums4.delimited_value not in (Nums1.delimited_value, Nums2.delimited_value, Nums3.delimited_value)
GROUP BY CAST(Nums1.delimited_value AS VARCHAR)
,ISNULL(CAST(Nums2.delimited_value AS VARCHAR),'')
,ISNULL(CAST(Nums3.delimited_value AS VARCHAR),'')
,CAST(Nums4.delimited_value AS VARCHAR) WITH ROLLUP
If you will potentially have more than 3 or 4, you'll want to expand your code accordingly.

Can you create nested WITH clauses for Common Table Expressions?

WITH y AS (
WITH x AS (
SELECT * FROM MyTable
)
SELECT * FROM x
)
SELECT * FROM y
Does something like this work? I tried it earlier but I couldn't get it to work.
While not strictly nested, you can use common table expressions to reuse previous queries in subsequent ones.
To do this, the form of the statement you are looking for would be
WITH x AS
(
SELECT * FROM MyTable
),
y AS
(
SELECT * FROM x
)
SELECT * FROM y
You can do the following, which is referred to as a recursive query:
WITH y
AS
(
SELECT x, y, z
FROM MyTable
WHERE [base_condition]
UNION ALL
SELECT x, y, z
FROM MyTable M
INNER JOIN y ON M.[some_other_condition] = y.[some_other_condition]
)
SELECT *
FROM y
You may not need this functionality. I've done the following just to organize my queries better:
WITH y
AS
(
SELECT *
FROM MyTable
WHERE [base_condition]
),
x
AS
(
SELECT *
FROM y
WHERE [something_else]
)
SELECT *
FROM x
With does not work embedded, but it does work consecutive
;WITH A AS(
...
),
B AS(
...
)
SELECT *
FROM A
UNION ALL
SELECT *
FROM B
EDIT
Fixed the syntax...
Also, have a look at the following example
SQLFiddle DEMO
These answers are pretty good, but as far as getting the items to order properly, you'd be better off looking at this article
http://dataeducation.com/dr-output-or-how-i-learned-to-stop-worrying-and-love-the-merge
Here's an example of his query.
WITH paths AS (
SELECT
EmployeeID,
CONVERT(VARCHAR(900), CONCAT('.', EmployeeID, '.')) AS FullPath
FROM EmployeeHierarchyWide
WHERE ManagerID IS NULL
UNION ALL
SELECT
ehw.EmployeeID,
CONVERT(VARCHAR(900), CONCAT(p.FullPath, ehw.EmployeeID, '.')) AS FullPath
FROM paths AS p
JOIN EmployeeHierarchyWide AS ehw ON ehw.ManagerID = p.EmployeeID
)
SELECT * FROM paths order by FullPath
we can create nested cte.please see the below cte in example
;with cte_data as
(
Select * from [HumanResources].[Department]
),cte_data1 as
(
Select * from [HumanResources].[Department]
)
select * from cte_data,cte_data1
I was trying to measure the time between events with the exception of what one entry that has multiple processes between the start and end. I needed this in the context of other single line processes.
I used a select with an inner join as my select statement within the Nth cte. The second cte I needed to extract the start date on X and end date on Y and used 1 as an id value to left join to put them on a single line.
Works for me, hope this helps.
cte_extract
as
(
select ps.Process as ProcessEvent
, ps.ProcessStartDate
, ps.ProcessEndDate
-- select strt.*
from dbo.tbl_some_table ps
inner join (select max(ProcessStatusId) ProcessStatusId
from dbo.tbl_some_table
where Process = 'some_extract_tbl'
and convert(varchar(10), ProcessStartDate, 112) < '29991231'
) strt on strt.ProcessStatusId = ps.ProcessStatusID
),
cte_rls
as
(
select 'Sample' as ProcessEvent,
x.ProcessStartDate, y.ProcessEndDate from (
select 1 as Id, ps.Process as ProcessEvent
, ps.ProcessStartDate
, ps.ProcessEndDate
-- select strt.*
from dbo.tbl_some_table ps
inner join (select max(ProcessStatusId) ProcessStatusId
from dbo.tbl_some_table
where Process = 'XX Prcss'
and convert(varchar(10), ProcessStartDate, 112) < '29991231'
) strt on strt.ProcessStatusId = ps.ProcessStatusID
) x
left join (
select 1 as Id, ps.Process as ProcessEvent
, ps.ProcessStartDate
, ps.ProcessEndDate
-- select strt.*
from dbo.tbl_some_table ps
inner join (select max(ProcessStatusId) ProcessStatusId
from dbo.tbl_some_table
where Process = 'YY Prcss Cmpltd'
and convert(varchar(10), ProcessEndDate, 112) < '29991231'
) enddt on enddt.ProcessStatusId = ps.ProcessStatusID
) y on y.Id = x.Id
),
.... other ctes
Nested 'With' is not supported, but you can always use the second With as a subquery, for example:
WITH A AS (
--WITH B AS ( SELECT COUNT(1) AS _CT FROM C ) SELECT CASE _CT WHEN 1 THEN 1 ELSE 0 END FROM B --doesn't work
SELECT CASE WHEN count = 1 THEN 1 ELSE 0 END AS CT FROM (SELECT COUNT(1) AS count FROM dual)
union all
select 100 AS CT from dual
)
select CT FROM A