How to get minimum fare between two cities - c#

I have below table
Source Destination Fare
A B 10
B C 5
B D 1
D C 1
A D 1
Now I wanted to write a query which will give me the minimum fare between two cities.
For example if I want to go A->C then minimum fare is 2 A->D->C
What will be MS-Sql query for this problem.

Try this:
;WITH Paths AS (
-- Anchor query: get first step
SELECT CAST(CONCAT(Source, '->', Destination) AS VARCHAR(MAX)) AS Path,
Destination, Fare,
IIF(Destination = 'C', 1, 0) AS Terminate
FROM mytable
WHERE Source = 'A'
UNION ALL
-- Recursive part: get next step
SELECT CAST(CONCAT(Path, '->', t.Destination) AS VARCHAR(MAX)) AS Path,
t.Destination, Fare = t.Fare + p.Fare,
IIF(t.Destination = 'C', 1, 0) AS Terminate
FROM mytable AS t
JOIN Paths AS p ON t.Source = p.Destination
WHERE p.Destination <> 'C'
)
SELECT Path, Fare
FROM (
SELECT Path, Fare,
RANK() OVER (ORDER BY Fare) AS rnk
FROM Paths
WHERE Terminate = 1) AS t
WHERE t.rnk = 1
This is sort of a brute force method: it uses a recursive CTE to get all possible paths. Then using RANK we can select the one(s) having the minimum fare.
Demo here

have you try to google:
sql server travelling salesman
or
sql server shortest path
There are tons of answers

Related

Leaderboard, rank query, how to return the rows above/below a users rank

Given this query, if I want to pull the rank of a specific individual where I know there $name and $score and return the rows above/below that rank (say +/- 4), how would I go about doing that?
$query = "SELECT #curRank := #curRank + 1 AS Rank,
uniqueID,
name,
score
FROM scores, (SELECT #curRank := 0) r
ORDER by score DESC";
I'm coding in php, using MySQL and C# in Unity. My game is making a call to the server and running the php code. Goal is to echo the information and parse the information back in the game.
Any help would be much appreciated :)
Based off of your :=, I'm assuming you are using PostgreSQL, correct? I'm more familiar with the T-SQL syntax; but regardless, both PostgreSQL and T-SQL have windowing functions. You could implement something similar to the following (I left out variables for you to fill-in):
$query = "WITH scoreOrder
AS
(
SELECT uniqueID,
name,
score,
ROW_NUMBER() OVER (ORDER BY score DESC, uniqueID DESC) AS RowNum
FROM scores
ORDER BY uniqueID DESC
)
SELECT ns.*
FROM scoreOrder ms --Your matching score
INNER JOIN scoreOrder ns --Your nearby scores
ON ms.name = /* your name variable */
AND ms.score = /* your score variable */
AND ns.RowNum BETWEEN ms.RowNum - /* your offset */ and ms.RowNum + /* your offset */";
Explanation: First, we're creating a common table expression called scoreOrder, and projecting a RowNum column for your scores. In short, ROW_NUMBER() OVER (ORDER BY score DESC, uniqueID DESC) is just saying, "I am returning the row number of this record ordered by score and uniqueID, both descending and in that order." Then, you join that CTE with itself... ms will be your score that you match with, and you join that with ns where the ns.RowNum will be between your ms.RowNum, plus or minus your offset.
There are a ton of other windowing functions. Here are some others that could be more or less appropriate for your scenario:
ROW_NUMBER() - the rownumber of the record
RANK() - the rank of the record, duplicating in ties and includes
gaps (i.e., if 2nd place ties, you would have 1st, 2nd, 2nd,
4th)
DENSE_RANK() - same as rank, except that it fills in the gaps
(i.e., if 2nd place ties, you would have 1st, 2nd, 2nd, 3rd)
For more info, check the PostgreSQL documentation on windowing functions and their tutorial
Update:
Unfornately, MySQL does not support windowing functions or common table expressions. In your scenario, you will have to put the results of your previous query into a temp table, then doing a similar join as demonstrated above. So for example...
CREATE TEMPORARY TABLE IF NOT EXISTS allRankings AS
(
SELECT #curRank := #curRank + 1 AS Rank,
uniqueID,
name,
score
FROM scores, (SELECT #curRank := 0) r
ORDER by score DESC, uniqueID
);
SELECT r.*
FROM allRankings r
INNER JOIN allRankings myRank
ON r.Rank BETWEEN myRank.Rank - <your offset> AND myRank.Rank + <your offset>
AND myRank.name = <your name>
AND myRank.score = <your score>
ORDER by r.Rank;
Here is a SQLFiddle link for an example. (I'm not using a temp table on SQLFiddle because you have to build tables in the Build Schema window).

SQL Query to run a select query Soccer league table

Here is my query. I have a colomun name "Played" (int). I update it as one if a match is played. so sum it later. Now i want number of matches played by a team to this query. But I have no idea how to add that.
Select DENSE_RANK() OVER(order by Point DESC,GD DESC) as Rank, * from (select TName, Sum(Score) as Score, Sum(GA) as GA,Sum(Diff) as GD,Sum(Point) as Point from (Select f.teamID,Score as Score, GA as GA,Score-GA as DIff,
case
when Result = 'W' then 3
when Result = 'D' then 1
Else 0
end as Point, T.TName,
from Fixtures F
inner join Teams T on t.TeamID = f.TeamID ) S
group by teamID,TName) SS
order by Point DESC,GD DESC
Do a count on result. That would get how many games they played

How to set an integer value to one if a record exist in database C# Sql Query

getName_as_Rows is an array which contains some names.
I want to set an int value to 1 if record found in data base.
for(int i = 0; i<100; i++)
{
using (var command = new SqlCommand("select some column from some table where column = #Value", con1))
{
command.Parameters.AddWithValue("#Value", getName_as_Rows[i]);
con1.Open();
command.ExecuteNonQuery();
}
}
I am looking for:
bool recordexist;
if the above record exist then bool = 1 else 0 with in the loop.
If have to do some other stuff if the record exist.
To avoid making N queries to the database, something that could be very expensive in terms of processing, network and so worth, I suggest you to Join only once using a trick I learned. First you need a function in your database that splits a string into a table.
CREATE FUNCTION [DelimitedSplit8K]
--===== Define I/O parameters
(#pString VARCHAR(8000), #pDelimiter CHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
--===== "Inline" CTE Driven "Tally Table" produces values from 0 up to 10,000...
-- enough to cover VARCHAR(8000)
WITH E1(N) 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
), --10E+1 or 10 rows
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS (--==== This provides the "zero base" and limits the number of rows right up front
-- for both a performance gain and prevention of accidental "overruns"
SELECT 0 UNION ALL
SELECT TOP (DATALENGTH(ISNULL(#pString,1))) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
SELECT t.N+1
FROM cteTally t
WHERE (SUBSTRING(#pString,t.N,1) = #pDelimiter OR t.N = 0)
)
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY s.N1),
Item = SUBSTRING(#pString,s.N1,ISNULL(NULLIF(CHARINDEX(#pDelimiter,#pString,s.N1),0)-s.N1,8000))
FROM cteStart s
GO
Second, concatenate your 100 variables into 1 string:
"Value1", "Value 2", "Value 3"....
In Sql Server you can just join the values with your table
SELECT somecolumn FROM sometable t
INNER JOIN [DelimitedSplit8K](#DelimitedString, ',') v ON v.Item = t.somecolumn
So you find 100 strings at a time with only 1 query.
Use var result = command.ExecuteScalar() and check if result != null
But a better option than to loop would be to say use a select statement like
SELECT COUNT(*) FROM TABLE WHERE COLUMNVAL >= 0 AND COLUMNVAL < 100,
and run ExecuteScalar on that, and if the value is > 0, then set your variable to 1.

ORA-01858: a non-numeric character was found where a numeric was expected

I have a function that takes in a collection of SearchCriteria Objects:
columnName or Key, operator (<, <=, like, etc), and value.
The function builds up a Command Object.
I made the value a command parameter and now my Unit Tests will not work for Dates.
But all of my Unit Tests work against all other datatypes like varchar.
In the debugger, one of my date unit tests that fail end up with the cmd looking like this:
SELECT * FROM (SELECT DocumentId
FROM idx1_AuthLetters a
INNER JOIN Documents b ON a.DocumentId = b.Id
WHERE Status in ('L','S','V') AND letter_date <= :1
ORDER BY DOCUMENTID )
WHERE RowNum <= 14
I did have the parameter named like :letter_date. But I might have :letter_date >= ### && :letter_date <= ### where I am looking between two dates. I cannot have the same parameter name twice so I use an i++ counter as parameter name while I am looping through all of my SearchCriteria Objects. Odd to see a parameter named like this I know but it is working for the most part.
If I take this and put in my Query Window, and look inspect the param value and plug that in:
SELECT * FROM (SELECT DocumentId
FROM idx1_AuthLetters a
INNER JOIN Documents b ON a.DocumentId = b.Id
WHERE Status in ('L','S','V') AND
letter_date <= TO_DATE('2013-1-21', 'yyyy-mm-dd')
ORDER BY DOCUMENTID )
WHERE RowNum <= 14
it works fine.
But it will not work from the C# code from my Unit Test.
Again this works for all other data types.
And it use to work before I parameterized the value in the select statement.
Exact error is:
{"ORA-01858: a non-numeric character was found where a numeric was expected"}
The answer is really simple here:
In your command, build the following string TO_DATE(:1, 'yyyy-mm-dd') . Then, just make sure that string that goes into :1 has accurate format.
Your command text should be this:
SELECT * FROM (SELECT DocumentId
FROM idx1_AuthLetters a
INNER JOIN Documents b ON a.DocumentId = b.Id
WHERE Status in ('L','S','V') AND letter_date <= TO_DATE(:1, 'yyyy-mm-dd')
ORDER BY DOCUMENTID )
WHERE RowNum <= 14

N-tiered Parent/Child Breadcrumb Trail - Bottom to Top Loop

I am trying to building a breadcrumb trail based on a parent/child relationship in a SQL database table. I have done these in the past, but what I need to do now is walk my way up through the hierarchy from the bottom up (backwards).
Here is what my DataTable looks like:
DocID | ParentDocID | Name
7 | 0 | Images (Root)
24 | 7 | JPG (Level 2)
34 | 24 | Size (Level 3)
So this is an N-tiered architecture. I always know what level I am at via a query string variable. I need to loop from the bottom up so that a user can bookmark what level in the tier structure they are at. I am having trouble figuring this out. I cannot use session or viewstate.
Desired Results:
User goes to this link:
Default.aspx?DocId=34 – Then they see the breadcrumb trail as such:
Home > Images > JPG > Size
Default.aspx?DocId=24 – Then they see the breadcrumb trail as such:
Home > Images > JPG
The “Home” element I have hard-coded. I also need each item in the trail to link except for the level you are on.
I would rather this be done in C# code. I also am open to SQL level Stored Procedure options.
Any help would be greatly appreciated. Thank-you in advance!
Here is some SQL I am trying but not getting the results I need. I hope this helps:
WITH Hierachy([DocID], [ParentDocID], [Name], [Level]
AS
(
SELECT [DocID], [ParentDocID], [Name], 0 AS [Level]
FROM [Documents] d
WHERE (d.[ParentDocID] = 7) AND ([Folder] = 1) AND ([Status] = 'A') AND ([AppGroupID] = 4)
UNION ALL
SELECT d.[DocID], d.[ParentDocID], d.[Name], dh.[Level] + 1
FROM [Documents] d
INNER JOIN Hierachy dh
--ON d.ParentDocID = dh.DocID
ON dh.[ParentDocID] = d.[DocID] -- bottom up apporach
WHERE ([Folder] = 1) AND ([Status] = 'A') AND ([AppGroupID] = 4)
)
SELECT [DocID], [ParentDocID], [Name]
FROM Hierachy
--WHERE [Level] > 0
I got it! Here is the SQL that works:
WITH Hierachy([DocID], [ParentDocID], [Name], [Level])
AS
(
SELECT [DocID], [ParentDocID], [Name], 0 AS [Level]
FROM [Documents] d
WHERE (d.[DocID] = #ParentDocID) AND ([Folder] = 1)
AND ([Status] = 'A') AND ([AppGroupID] = #AppGroupID)
UNION ALL
SELECT d.[DocID], d.[ParentDocID], d.[Name], dh.[Level] + 1
FROM [Documents] d
INNER JOIN Hierachy dh
ON dh.[ParentDocID] = d.[DocID]
WHERE ([Folder] = 1)
AND ([Status] = 'A') AND ([AppGroupID] = #AppGroupID)
)
SELECT [DocID], [ParentDocID], [Name]
FROM Hierachy
ORDER BY [Level] DESC
)
Sure you can. You can use CURSOR or WHILE LOOP or XML.
I have an example like you. Here's the WHILE LOOP with a temp Table, it selects parents of a node with a provided ID:
DECLARE #ID INT = 4
DECLARE #Parent_ID INT
DECLARE #Tree TABLE
(
ID int,
Value NVARCHAR(10),
Parent_ID int
)
SELECT #Parent_ID = Parent_ID FROM Tree
WHERE ID = #ID
WHILE #Parent_ID IS NOT NULL
BEGIN
INSERT INTO #Tree
SELECT * FROM Tree
WHERE ID = #Parent_ID
SELECT #Parent_ID = Parent_ID FROM Tree
WHERE ID = #Parent_ID
END
SELECT * FROM #Tree
This describes solving a similar problem, ie walking up a tree. Any inline sql, such as this is best executed within a stored procedure. Solving it in SQL is probably the best approach, as you already have all the data there.
Check below link you will get perfact answer for your question.
SQL Server: How to get all child records given a parent id in a self referencing table

Categories

Resources