How to sort varchar row by asc? - sql

I have a column Cardnumber from Employees table. The row of a column contains the number of card: 0578391322177.
How can I sort the numbers in the row by asc and get 0112233577789?
The data type is varchar.

Ideally you would have a numbers or tally table to hand; you can build one on the fly using a CTE however.
You can join this to a substring of each character, then recombine using string_agg and order appropriately. This is assuming the card numbers are all the same length - if not adjust the CTE and include a where criteria to be <= len(string).
declare #n varchar(13)='0578391322177';
with digits as (
select *
from (
values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13)
)v(n)
)
select String_Agg(n.d,'') within group (order by n.d)
from (
select substring(#n,n,1)d
from Digits
)n
Output: 0112233577789
Edit
As an example of using with data from a table you would do
select Id, cardnumber, String_Agg(n.d,'') within group (order by n.d) SortedCardNumber
from (
select t.Id, t.cardnumber, Substring(t.cardnumber,n,1)d
from
t cross join Digits d
where d.n<=Len(t.cardnumber)
)n
group by Id, cardnumber
See DB<>Fiddle

Related

How create a unique ID based on conditions in SQL?

I would like to get a new ID, no matter the format (in the example below 11,12,13...)
Based on the following condition:
Every time the days column value is greater then 1 and not null then current row and all following ones will get the same ID until a new value will meet the condition.
Within the same email
Below you can see the expected 1 (in the format of XX)
I thought about using two conditions with the following order between them
Every time the days column value is greater then 1 then all following rows will get the same ID until a new value will meet the condition.
2.AND When lag (previous) is equal to 0/1/null.
Assuming you have an EmailDate column over which you're ordering (a DATETIME field, really), try something like this:
WITH
TableNameWithEmailDateIDs AS (
SELECT
*,
ROW_NUMBER() OVER (
ORDER BY
Email DESC,
EmailDate
) AS EmailDateID
FROM
TableName
),
IDs AS (
SELECT
*,
LEAD(EmailDateID, 1) OVER (
ORDER BY
Email,
EmailDate
) AS LeadEmailDateID
FROM
(
SELECT
*,
-- REMOVE +10 if you don't want 11 to be starting ID
ROW_NUMBER() OVER (
ORDER BY
Email DESC,
EmailDate
)+10 AS ID
FROM
TableNameWithEmailDateIDs
WHERE
Days > 1
OR Days IS NULL
) X
)
SELECT
COALESCE(TableName.EmailDate, IDs.EmailDate) AS EmailDate,
IDs.Email,
COALESCE(TableName.Days, IDs.Days) AS Days,
IDs.ID
FROM
IDs
LEFT JOIN TableNameWithEmailDateIDs TableName
ON IDs.Email = TableName.Email
AND TableName.EmailDateID BETWEEN
IDs.EmailDateID
AND IDs.LeadEmailDateID-1
ORDER BY
ID DESC,
TableName.EmailDate DESC
;
First, create a CTE that generates IDs for each distinct Email/Date combo (helpful for LEFT JOIN condition later). Then, create a CTE that generates IDs for rows that meet your condition (i.e. the important rows). Finally, LEFT JOIN your main table onto that CTE to fill in the "gaps", so to speak.
I suggest running each of the components of this query independently to fully understand what's going on.
Hope it helps!

Using Derby SQL to calculate value for histogram

I have a table with various SKU in totes.
The table is totecontents with below columns:
ToteID
SKU
Each Tote can contain a maximum of 6 SKUs. (programmatically constrained)
select toteid, count(*) as qtypertote
from totecontents
group by toteid;
gives me a list of totes with the number of skus in each.
I now want to get to a table with following result
SkuCount Occurences where each row would have the ordinal value (1 through 6 ) and then the number of occurences of that value.
My efforts included the following approach
select count(*)
from
( select toteid, count(*) as qtypertote
from totecontents
group by toteid)
group by qtypertote;
Stung by the comments I performed more research. This works:
SELECT CountOfskus, COUNT(1) groupedCount
FROM
( SELECT COUNT(*) as countofskus, toteid
FROM totecontents
Group By toteid
) MyTable
GROUP BY countofskus;

How to write a query, to produce the desired result?

I want to use a query, showing the top two best Quantity. If the table is like the picture, how can the desired result be produced
You can use DENSE_RANK(). For example:
select
id, name, quantity
from (
select
id, name, quantity,
dense_rank() over(order by quantity desc) as rk
from t
) x
where rk <= 2
DENSE_RANK() computes a number for each row according to an ordering of your choosing. Identical values get the same number, and no numbers are skipped. See SQL Fiddle.
You can use the TOP/LIMIT functions in query. Which would allow you to select a specific number of rows.
using number as 5 you can get the desired result from:
SELECT columnname FROM tablename WHERE condition LIMIT number;
or
SELECT TOP (number)/(percent) columnname FROM tablename WHERE condition;

Problems with ordering sql server order by clause

Check Image
I have a problem with an order by sql server, I need to sort the records in the Ejey field, as follows:
Alta/Deficiente
Baja/Optima
Deficiente/Deficiente
Media/Alta
Optima/Deficiente
.... So Suspensively
As shown by the selected records in gray, I clarify that my table of the image has 625 records and the other fields must remain the same.
As far as each value of EjeY has the same count of rows (5) one idea is to order the rows by the modulo of its row's row number with this count.
This could work:
--Save your data in a temp table ordered by the value of EjeY column
SELECT *
INTO #TEMP2
FROM
(
SELECT *
FROM YouTable
) AS TEMP1
ORDER BY TEMP1.EjeY --Here you modify the ordering mode you want every time your EjeY values to be displayed
--For each row of the temp table calculate the module the row number
--with the count of rows per EjeY value
--(that must be 5 in your situation)
--and order the table by this value and then by row number)
SELECT
row_col%(select top 1 count(EjeY) from YouTable group by EjeY) AS mod_col,
row_col,
TEMP3.* --your columns
FROM
(SELECT *,
ROW_NUMBER() OVER (ORDER BY (SELECT null))-1 as row_col
FROM #TEMP2) as TEMP3
ORDER BY mod_col,TEMP3.row_col

SQL Command for the following table

I have a table named with "Sales" having the following columns:
Sales_ID|Product_Code|Zone|District|State|Distributor|Total_Sales
Now i want to generate a sales summary to view the total sales by zone and then by district and then by State by which distributor for the last/past month period.
How can i write a Sql Statement to do this? Can anyone help me Plz. Thanks in advance.
And i have another question that, how can i select the second largest or third largest values from any column of a table.
Have a look at using the ROLLUP GROUP BY option.
Generates the simple GROUP BY aggregate rows, plus subtotal or super-aggregate rows,
and also a grand total row.
The number of groupings that is returned equals the number of expressions
in the <composite element list> plus one. For example, consider the following statement.
Copy Code
SELECT a, b, c, SUM ( <expression> )
FROM T
GROUP BY ROLLUP (a,b,c)
One row with a subtotal is generated for each unique combination of values of
(a, b, c), (a, b), and (a). A grand total row is also calculated.
Columns are rolled up from right to left.
The column order affects the output groupings of ROLLUP and can affect the number
of rows in the result set.
Something like
DECLARE #Table TABLE(
Zone VARCHAR(10),
District VARCHAR(10),
State VARCHAR(10),
Sales FLOAT
)
INSERT INTO #Table SELECT 'A','A','A',1
INSERT INTO #Table SELECT 'A','A','B',1
INSERT INTO #Table SELECT 'A','B','A',1
INSERT INTO #Table SELECT 'B','A','A',1
SELECT Zone,
District,
State,
SUM(Sales)
FROM #Table
WHERE <Your Condition here> --THIS IS WHERE YOU USE THE WHERE CLAUSE
GROUP BY ROLLUP (Zone,District,State)
To Get the second and 3rd largets, you can use either (ROW_NUMBER (Transact-SQL))
;WITH Vals AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY RequiredCol DESC) RowNum
FROM YourTable
)
SELECT *
FROM Vals
WHERE RowNum IN (2,3)
or
SELECT TOP 2
*
FROM (
SELECT TOP 3
*
FROM YourTable
ORDER BY RequiredCol DESC
) sub
ORDER BY RequiredCol
SELECT SUM(Total_Sales) FROM sales GROUP BY (X)
Replace X with Zone, District, State or Distributor.