select max of mixed string/int column - sql

I have a table who returns me a value as bellow
id_unique name serie timeB timeD
155488EA-FF70-49D7-99AB-AFD4125F3435 dell 14296188 05:51 06:19
1B640883-0DB6-4255-B1ED-770B6578064C dell 14295943 04:37 04:39
I want the max of the value i have tried a sql as bellow :
select max(cast(id_unique as varchar(36))),
max(name),max(serie),max(timeB),max(timeD) from mytable group by name
i got this result
1B640883-0DB6-4255-B1ED-770B6578064C dell 14296188 05:51 06:19
But the result that i need is this one :
155488EA-FF70-49D7-99AB-AFD4125F3435 dell 14296188 05:51 06:19
This any metho to fix that ?

My guess is that you want something like this using row_number:
select *
from (
select *, row_number() over (order by somevalue desc) rn
from yourtable
) t
where rn = 1
Where somevalue is the column you need the max of. I presume you are currently trying to use max for every field -- that would explain your output...

If these are really stored as strings, I'm guessing that you want to cast the first column as a uniqueidentifier before finding the max, otherwise they will be evaluated alphabetically.
SQL Server 2012 and above
You can directly get the min/max of uniqueidentifiers:
select max(cast(id_unique as uniqueidentifier))
from MyTable
Previous Versions
You should cast as binary(16) before finding the min/max. I'm then casting back to uniqueidentifier for readability of the results:
select cast(max(cast(cast(id_unique as uniqueidentifier) as binary(16))) as uniqueidentifier)
from MyTable

Related

Get maximum value in a column in sql query if the column is alphanumeric

This is the table which I have by name project and it contains 3 columns:
estimateId
name
projectName
I want to fetch data from SQL database based on maximum value of estimateId
but here estimateid is alphanumeric. How can I achieve this.
I need a SQL query to achieve this:
For example estimateId contains values like:
Elooo1
Elooo2
......
Elooo10
and so on. So how can I achieve this?
Setup Testing Data
DECLARE #tmpTable TABLE ( estimateId NVARCHAR(MAX));
INSERT into #tmpTable(estimateId) VALUES ('Elooo1'),('Elooo2'),('Elooo3'),('Elooo4'),('Elooo5'),('Elooo6');
Split data based on the pattern
SELECT T.prefix AS prefix, MAX(T.suffix) AS suffix, MAX(estimateId) AS estimateId FROM (SELECT estimateId,LEFT(estimateId, PATINDEX('%[a-zA-Z][^a-zA-Z]%', estimateId )) AS prefix,LTRIM(RIGHT(estimateId, LEN(estimateId) - PATINDEX('%[a-zA-Z][^a-zA-Z]%', estimateId ))) As suffix FROM #tmpTable) T GROUP BY T.prefix
Result
prefix suffix estimateId
Elooo 6 Elooo6
Reference
split alpha and numeric using sql
I just started SQL like today.. so i'm totally a newbie, but I think I could solve your problem. I would do something like this
SELECT name, projectName FROM table ORDER BY estimateId ASC
or (I think you will need ORDER BY ... DESC)
SELECT name, projectName FROM table ORDER BY estimateId DESC
You seem to be looking to extract the numeric part of the strings. Assuming that the strings have variable length, and that the numbers are always at the end, you can do:
try_cast(
substring(estimateId, patindex('%[0-9]%', estimateId), len(estimateId))
as int
)
This captures everything from the the first number in the string to the end of the string, and attempts to convert it to a number (if the conversion fails, try_cast() returns null rather than raising an error).
It is not very clear what you want to use this information for. For example, if you wanted to sort your data accordingly, you would do:
select *
from mytable
order by try_cast(
substring(estimateId, patindex('%[0-9]%', estimateId), len(estimateId))
as int
)

Convert XML to table SQL Server 2005

I wonder how I can read a XML data and transform it to a table in T-SQL?
For example:
<t1>
<t2>
<val>Opel</val>
<t3>Merriva</t3>
<t3>Zafira</t3>
</t2>
<t2>
<val>Fiat</val>
<t3>Albea</t3>
</t2>
</t1>
To:
Table1:
id value
----------------
1 Opel
2 Fiat
Table2:
id id_Table1 value
-----------------------------------
1 1 Merriva
2 1 Zafira
3 2 Albea
I don't have an active SQL-Server 2005 to test this (boy, it's 2018...!!!), but I think, that this query would work in such ancient versions too:
DECLARE #xml XML=
N'<t1>
<t2>
<val>Opel</val>
<t3>Merriva</t3>
<t3>Zafira</t3>
</t2>
<t2>
<val>Fiat</val>
<t3>Albea</t3>
</t2>
</t1>';
--The CTE will return the CarName with a running index together with the related data as XML-node
WITH Cars AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS t2_index
,t2.value(N'(val/text())[1]',N'nvarchar(100)') AS t2_val
,t2.query(N't3') AS t3_nodes
FROM #xml.nodes(N'/t1/t2') A(t2)
)
--This part will append all related data with a running number for the related type data
SELECT Cars.*
,ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) AS CarValueIndex
,t3.value(N'text()[1]',N'nvarchar(100)') AS CarValue
INTO #tmpCars --write the result into a temp table
FROM Cars
OUTER APPLY t3_nodes.nodes(N't3') A(t3);
--All data de-normalized
SELECT * FROM #tmpCars;
--This query will bring back the parent rows
SELECT t2_index AS CarID
,t2_val AS CarName
FROM #tmpCars
GROUP BY t2_index,t2_val;
--And this query will return the related child data
SELECT CarValueIndex AS CarTypeID
,t2_index AS fk_CarID
,CarValue AS CarType
FROM #tmpCars;
GO
DROP TABLE #tmpCars;
If there is any chance to move to a more modern SQL-Server you really should do it...
UPDATE
According to this link, the .value() and .nodes() function were introduced with v2008. But I have a dark memory, that it was working in 2005 already, might be together with some service packs... Try it out.

where clauses in max statement

how it is possible to add where to query , to do converting or replacing or max value!
max(convert(int,replace(( QueueNum ),'-',''))) from [Queue]
i want to return max of records that have something special , in where clauses for QueueNum .
Edited :
Data :
1981-1-1232
1981-1-1235
1981-1-1234
1981-2-1
1981-2-2
1981-2-13
how it is possible to return max value of just record started with 1981-2
I guess it is MSSql database in this case try to use the following statement without any conversion:
SQLfiddle demo
select TOP 1
QueueNum
from Queue where QueueNum like '1981-2-%'
order by LEN(QueueNum) desc, QueueNum desc
Not sure if I am giving a good answer, but you can write your query as
Select max(MyValue) from (Select Convert(int, replace((QueueNum),'-','')) as MyValue from [Queue]) MyTable
What it does is that it create a Temporary table in memory which is of one column MyValue and of type Int, this then find Max from that table. I notice that sometime "MyTable" [table alias] is important in such query to perform especially on SQl Server.
Put your condition in having clause
Is this what you want?
SELECT MAX(CONVERT(INT, REPLACE((QueueNum),'-','')))
FROM Queue
WHERE QueueNum LIKE '1981-2%'
SQLFiddle.

SQL Server: Using CHARINDEX to parse multiplying problems

I have a data column that stores products distribution units as 1*1 or 1*2*6. I want to formulate a computed column and have the result of the multiply problem.
below is illustrated example
sku du computed_du
12345678 1*2 2
12345679 1*3 3
12345680 1*6*2 12
Is there a most effective way to perform this calculation on sql server?
This is definitely something that should be calculated elsewhere, but I have seen the below technique used as a crude product aggregation.
I am not positive about using this for computed column, but here is how you might pull it off: Wrap this in a function, schema bind it to your table, and reference it the computed column definition (not sure if mssql will allow this due to deterministic requirement of udf).
Uses split function from here.
declare #tab table (
sku int,
du varchar(10),
computed_du int
)
insert into #tab
select 12345678, '1*2', null union all
select 12345679, '1*3', null union all
select 12345680, '1*6*2*0', null
--
select sku, du, min(s), case when min(cast(s as int)) = 0 then 0 else exp(sum(log(cast(nullif(s, 0) as int)))) end
from #tab
cross
apply dbo.Split('*', du)d
where cast(s as int)>0
group
by sku, du;

Sql query that numerates the returned result

How to write one SQL query that selects a column from a table but returns two columns where the additional one contains an index of the row (a new one, starting with 1 to n). It must be without using functions that do that (like row_number()).
Any ideas?
Edit: it must be a one-select query
You can do this on any database:
SELECT (SELECT COUNT (1) FROM field_company fc2
WHERE fc2.field_company_id <= fc.field_company_id) AS row_num,
fc.field_company_name
FROM field_company fc
SET NOCOUNT ON
DECLARE #item_table TABLE
(
row_num INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, --THE IDENTITY STATEMENT IS IMPORTANT!
field_company_name VARCHAR(255)
)
INSERT INTO #item_table
SELECT field_company_name FROM field_company
SELECT * FROM #item_table
if you are using Oracle or a database that supports Sequence objects, make a new db sequence object for this purpose. Next create a view, and run this.
insert into the view as select column_name, sequence.next from table
In mysql you can :
SELECT Row,Column1
FROM (SELECT #row := #row + 1 AS Row, Column1 FROM table1 )
As derived1
I figured out a hackish way to do this that I'm a bit ashamed of. On Postgres 8.1:
SELECT generate_series, (SELECT username FROM users LIMIT 1 OFFSET generate_series) FROM generate_series(0,(SELECT count(*) - 1 FROM users));
I believe this technique will work even if your source table does not have unique ids or identifiers.
On SQL Server 2005 and higher, you can use OVER to accomplish this:
SELECT rank() over (order by company_id) as rownum
, company_name
FROM company