SQL SELECT cannot reference "INDEX" column - sql

Using Advantage SQL, I have the following query:
SELECT TOP 10 mytable.*
FROM "mytable.ADT" mytable
ORDER BY date DESC
This returns this data set:
INDEX NR NAME Date
---------------------------------------------------
"145443" 115 Bob 19.03.2021 12:26
"23545",1 215 Steve 19.03.2021 12:09
"564543","",0 215 John 19.03.2021 12:09
"456234" 215 Mark 19.03.2021 12:09
What I want to do is work with the data in the INDEX column. But if I run a normal SELECT query with this field name:
SELECT mytable.INDEX etc
it doesn't run. I also cannot add it as an alias or anything.
Are there any workarounds to pull the specific column into a SELECT? My goal is to do text manipulation to remove the quote marks and extract only the pure number that sits in the middle.
This is the first time I've had this issue - I'm guessing the word INDEX is somehow a function name which screws things up. But I also am guessing there is a way around it?
Thanks.

INDEX is a SQL keyword -- and probably reserved, which is the problem.
You need to escape it. I believe Advantage supports both double quotes and square braces:
SELECT mytable."INDEX", mytable.[INDEX]
FROM "mytable.ADT" mytable
order by date desc
Note that capitalization is important in some databases (but not Advantage SQL) when you escape column names.

Related

SELECT from 50 columns

I have a table that has many columns around 50 columns that have datetime data that represent steps user takes when he/she do a procedure
SELECT UserID, Intro_Req_DateTime, Intro_Onset_DateTime, Intro_Comp_DateTime, Info_Req_DateTime, Info_Onset_DateTime, Info_Comp_DateTime,
Start_Req_DateTime, Start_Onset_DateTime, Start_Comp_DateTime,
Check_Req_DateTime, Check_Onset_DateTime, Check_Comp_DateTime,
Validate_Req_DateTime, Validate_Onset_DateTime, Validate_Comp_DateTime,
....
FROM MyTable
I want to find the Step the user did after certain datetime
example I want to find user ABC what the first step he did after 2 May 2019 17:25:36
I cannot use case to check this will take ages to code
is there an easier way to do that?
P.S. Thanks for everyone suggested redesigning the database.. not all databases can be redesigned, this database is for one of the big systems we have and it is been used for more than 20 years. redesigning is out of the equation.
You can use CROSS APPLY to unpivot the values. The syntax for UNPIVOT is rather cumbersome.
The actual query text should be rather manageable. No need for complicated CASE statements. Yes, you will have to explicitly list all 50 column names in the query text, you can't avoid that, but it will be only once.
SELECT TOP(1)
A.StepName
,A.dt
FROM
MyTable
CROSS APPLY
(
VALUES
('Intro_Req', Intro_Req_DateTime)
,('Intro_Onset', Intro_Onset_DateTime)
,('Intro_Comp', Intro_Comp_DateTime)
.........
) AS A (StepName, dt)
WHERE
MyTable.UserID = 'ABC'
AND A.dt > '2019-05-02T17:25:36'
ORDER BY dt DESC;
See also How to unpivot columns using CROSS APPLY in SQL Server 2012
The best way is to design your table with your action type and datetime that action was done. Then you can use a simple where clause to find what you want. The table should be like the table below:
ID ActionType ActionDatetime
----------- ----------- -------------------
1492 1 2019-05-13 10:10:10
1494 2 2019-05-13 11:10:10
1496 3 2019-05-13 12:10:10
1498 4 2019-05-13 13:10:10
1500 5 2019-05-13 14:10:10
But in your current solution, you should use UNPIVOT to get what you want. You can find more information in this LINK.

Concatenate /,: in a database row value after every 2 characters

I created a table in SQL Server and inserted values in that table columns in time column I stored a long string value which I retrieved from a log.
That log returns a time string like this '1103873704755', now I want to separate every 2 characters with /, (empty space) and K like this
'11/03/87 37:04:755'
Current query:
select top 1 Time
from tbl_ModBus
order by id desc
Output:
Time
-------------
1103873704755
Expected:
Time
-------------
11/03/87/ 37:04:755
So how can I get this string like I want using a SQL query?
I think that there is no a built in function to do this job in SQL.
It is always advised to use 'DATETIME ' when you are storing dates .
Yet, if you are storing data and time you better to use 'TIMESTAMP'.
Regarding all changes in the obtained value, you can do it in you programm code using whatever language you want !
I would not use a string save as DateTime.becasue it will be Unstable
If you only want to do concrete /,: in a database row value after every 2 characters.
The easiest way, you can try to use FORMAT function.
SELECT FORMAT(CAST('1103873704755' AS BIGINT),'##/##/## ##:##:###')
sqlfiddle
| |
|--------------------|
| 11/03/87 37:04:755 |

query, where field contains 2 t's

is there a way to perform a where clause that will match only 2 t's independent off where they are located.
such as
Matthew --
would work
Thanatos --
would work
Thanatos T --
would not work
Tom --
would not work
I've been Googling but cant find anything specific about this
any help is apreciated
You could try
SELECT *
FROM Table
WHERE Field LIKE '%t%t%' AND Field NOT LIKE '%t%t%t%'
I'm curious which would be faster, this or Goat CO's answer.
You could use LEN() and REPLACE():
SELECT *
FROM Table
WHERE LEN(REPLACE(field,'t','tt')) - LEN(Field) = 2
Demo: SQL Fiddle

Removing a column of data (string) by using LIKE query, there must be a better way

I have a problem with trying to remove a row of data based on a LIKE match in sql. I'm working with SQL Server 2005.
I have a table (#Containers) which holds information like below:-
PMBID DEPT
------ ---------
248057 5,8
249799 5,6,8
249800 5
249941 1,5
249942 1,4,15,16
249943 1,4,5
249945 4
249946 4
249947 4
249966 8,16,23
249967 5,6,8,16
Both columns are string, I need a query to be able to remove rows based on departments, for example if the PMBID has department 1,11,23, or 31 in it, it needs to be removed from the table. So with this logic PMBID's...
249941
249942
249943
249966
would be removed.
So how do I do this (well) in SQL seen as my column is string?
I've been writing queries such as...
DELETE FROM #Containers WHERE (Dept LIKE '%1%' OR Dept LIKE '%11%' OR Dept LIKE '%23%' OR Dept LIKE '%31%')
Obviously this statement doesn't work as it catches departments like 15, and 16, so for example PMBID
249967
would be included when it shouldn't as it's not explicitly a 1,11,23, or 31 (or a combination of these).
Is this possible with a string column? Can we use the delimiter somehow to improve the query?
I'll stop now as risk of over-complicating the query, please let me know if you need any further information.
The commas-in-the-list searching problem. Put commas around DEPT and around the values in the string:
DELETE FROM #Containers
WHERE (','+Dept+',' LIKE '%,1,%' OR
','+Dept+',' LIKE '%,11,%' OR
','+Dept+',' LIKE '%,23,%' OR
','+Dept+',' LIKE '%,31,%')
It is bad practice to store data in a comma delimited string, but this will work for department 1 as an example:
DELETE FROM #Containers
WHERE Dept LIKE '%,1'
OR Dept LIKE '1,%'
OR Dept LIKE '%,1,%'
You have to force commas into the criteria to exclude 1 from catching 11 and so on.
Might be cleaner to use a function that splits the string into individual values.
Here a good article on the subject:
http://www.sqlperformance.com/2012/07/t-sql-queries/split-strings

SQL Query with multiple values in one column

I've been beating my head on the desk trying to figure this one out. I have a table that stores job information, and reasons for a job not being completed. The reasons are numeric,01,02,03,etc. You can have two reasons for a pending job. If you select two reasons, they are stored in the same column, separated by a comma. This is an example from the JOBID table:
Job_Number User_Assigned PendingInfo
1 user1 01,02
There is another table named Pending, that stores what those values actually represent. 01=Not enough info, 02=Not enough time, 03=Waiting Review. Example:
Pending_Num PendingWord
01 Not Enough Info
02 Not Enough Time
What I'm trying to do is query the database to give me all the job numbers, users, pendinginfo, and pending reason. I can break out the first value, but can't figure out how to do the second. What my limited skills have so far:
select Job_number,user_assigned,SUBSTRING(pendinginfo,0,3),pendingword
from jobid,pending
where
SUBSTRING(pendinginfo,0,3)=pending.pending_num and
pendinginfo!='00,00' and
pendinginfo!='NULL'
What I would like to see for this example would be:
Job_Number User_Assigned PendingInfo PendingWord PendingInfo PendingWord
1 User1 01 Not Enough Info 02 Not Enough Time
Thanks in advance
You really shouldn't store multiple items in one column if your SQL is ever going to want to process them individually. The "SQL gymnastics" you have to perform in those cases are both ugly hacks and performance degraders.
The ideal solution is to split the individual items into separate columns and, for 3NF, move those columns to a separate table as rows if you really want to do it properly (but baby steps are probably okay if you're sure there will never be more than two reasons in the short-medium term).
Then your queries will be both simpler and faster.
However, if that's not an option, you can use the afore-mentioned SQL gymnastics to do something like:
where find ( ',' |fld| ',', ',02,' ) > 0
assuming your SQL dialect has a string search function (find in this case, but I think charindex for SQLServer).
This will ensure all sub-columns begin and start with a comma (comma plus field plus comma) and look for a specific desired value (with the commas on either side to ensure it's a full sub-column match).
If you can't control what the application puts in that column, I would opt for the DBA solution - DBA solutions are defined as those a DBA has to do to work around the inadequacies of their users :-).
Create two new columns in that table and make an insert/update trigger which will populate them with the two reasons that a user puts into the original column.
Then query those two new columns for specific values rather than trying to split apart the old column.
This means that the cost of splitting is only on row insert/update, not on _every single select`, amortising that cost efficiently.
Still, my answer is to re-do the schema. That will be the best way in the long term in terms of speed, readable queries and maintainability.
I hope you are just maintaining the code and it's not a brand new implementation.
Please consider to use a different approach using a support table like this:
JOBS TABLE
jobID | userID
--------------
1 | user13
2 | user32
3 | user44
--------------
PENDING TABLE
pendingID | pendingText
---------------------------
01 | Not Enough Info
02 | Not Enough Time
---------------------------
JOB_PENDING TABLE
jobID | pendingID
-----------------
1 | 01
1 | 02
2 | 01
3 | 03
3 | 01
-----------------
You can easily query this tables using JOIN or subqueries.
If you need retro-compatibility on your software you can add a view to reach this goal.
I have a tables like:
Events
---------
eventId int
eventTypeIds nvarchar(50)
...
EventTypes
--------------
eventTypeId
Description
...
Each Event can have multiple eventtypes specified.
All I do is write 2 procedures in my site code, not SQL code
One procedure converts the table field (eventTypeIds) value like "3,4,15,6" into a ViewState array, so I can use it any where in code.
This procedure does the opposite it collects any options your checked and converts it in
If changing the schema is an option (which it probably should be) shouldn't you implement a many-to-many relationship here so that you have a bridging table between the two items? That way, you would store the number and its wording in one table, jobs in another, and "failure reasons for jobs" in the bridging table...
Have a look at a similar question I answered here
;WITH Numbers AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 0)) AS N
FROM JobId
),
Split AS
(
SELECT JOB_NUMBER, USER_ASSIGNED, SUBSTRING(PENDING_INFO, Numbers.N, CHARINDEX(',', PENDING_INFO + ',', Numbers.N) - Numbers.N) AS PENDING_NUM
FROM JobId
JOIN Numbers ON Numbers.N <= DATALENGTH(PENDING_INFO) + 1
AND SUBSTRING(',' + PENDING_INFO, Numbers.N, 1) = ','
)
SELECT *
FROM Split JOIN Pending ON Split.PENDING_NUM = Pending.PENDING_NUM
The basic idea is that you have to multiply each row as many times as there are PENDING_NUMs. Then, extract the appropriate part of the string
While I agree with DBA perspective not to store multiple values in a single field it is doable, as bellow, practical for application logic and some performance issues. Let say you have 10000 user groups, each having average 1000 members. You may want to have a table user_groups with columns such as groupID and membersID. Your membersID column could be populated like this:
(',10,2001,20003,333,4520,') each number being a memberID, all separated with a comma. Add also a comma at the start and end of the data. Then your select would use like '%,someID,%'.
If you can not change your data ('01,02,03') or similar, let say you want rows containing 01 you still can use " select ... LIKE '01,%' OR '%,01' OR '%,01,%' " which will insure it match if at start, end or inside, while avoiding similar number (ie:101).