<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Di Cesare &#187; SQL</title>
	<atom:link href="http://www.dicesare.com/category/programmazione/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dicesare.com</link>
	<description></description>
	<lastBuildDate>Tue, 23 Mar 2010 22:38:55 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SQL: conteggi per fasce di valori</title>
		<link>http://www.dicesare.com/programmazione/sql/sql-conteggi-per-fasce-di-valori/</link>
		<comments>http://www.dicesare.com/programmazione/sql/sql-conteggi-per-fasce-di-valori/#comments</comments>
		<pubDate>Tue, 23 Mar 2010 11:02:56 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[2005]]></category>
		<category><![CDATA[CASE]]></category>
		<category><![CDATA[COUNT()]]></category>
		<category><![CDATA[GROUP BY]]></category>
		<category><![CDATA[INTERVAL]]></category>
		<category><![CDATA[MSSQL]]></category>
		<category><![CDATA[sql server]]></category>

		<guid isPermaLink="false">http://www.dicesare.com/programmazione/sql/sql-conteggi-per-fasce-di-valori/</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.00017800000000001 seconds-->
<!---Displayed in 0.0075609999999999 seconds.-->
In questo articolo spiegherò come ottenere una classificazione per fasce di una serie di valori.

Una delle classificazione classiche di una lista di valori è per fasce (di prezzo, ad esempio): quanti articoli costano meno di 100 Euro? Quanti tra 100 e 200? e così via.
La soluzione migliore sarebbe di inserire la fascia già nel record [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.000116 seconds-->
<!---Displayed in 0.005512 seconds.-->
<p>In questo articolo spiegherò come ottenere una classificazione per fasce di una serie di valori.<br />
<span id="more-1038"></span><br />
Una delle classificazione classiche di una lista di valori è per fasce (di prezzo, ad esempio): quanti articoli costano meno di 100 Euro? Quanti tra 100 e 200? e così via.</p>
<p>La soluzione migliore sarebbe di inserire la fascia già nel record da classificare, magari con un trigger. Questa però è una soluzione &#8217;statica&#8217;, che prevede una classificazione rigida decisa a priori.</p>
<p>Potrebbe invece essere necessario creare una classificazione arbitraria, momentanea e non decisa a priori.</p>
<p>Per ottenere questi tipo di prospetto, si può usare una combinazione di GROUP BY e CASE, come nell&#8217;esempio che segue:</p>
<pre class="brush: sql">
SELECT
   COUNT(Prezzo) AS [Numero Articoli],
	(CASE
		WHEN Prezzo&lt;1000 THEN &#039;Bassa&#039;
		WHEN Prezzo&gt;10000 THEN &#039;Alta&#039;
		ELSE &#039;Media&#039; END
         ) AS [Fascia di prezzo]
FROM
	Articoli
GROUP BY
	(CASE
		WHEN Prezzo&lt;1000 THEN &#039;Bassa&#039;
		WHEN Prezzo&gt;10000 THEN &#039;Alta&#039;
		ELSE &#039;Media&#039; END
        )
</pre>
<p>Otterremo quindi un elenco di quanti articoli sono nella fascia di prezzo &#8216;bassa&#8217; (meno di 1.000 Euro), quanti nella fascia &#8216;Media&#8217; (tra 1.000 e 10.000), e quanti nella fascia alta (più di 10.000 Euro).</p>
<p>Un&#8217;altra soluzione consiste nell&#8217;utilizzare una tabella di appoggio (fissa o temporanea) dove dichiarare le varie fasce, ed ottenere la classificazione con una JOIN.</p>
<p>Vedremo questa soluzione in un prossimo articolo.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/sql-conteggi-per-fasce-di-valori/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL: INSERT o UPDATE in automatico</title>
		<link>http://www.dicesare.com/programmazione/sql/sql-insert-o-update-in-automatico/</link>
		<comments>http://www.dicesare.com/programmazione/sql/sql-insert-o-update-in-automatico/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 17:07:22 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[2005]]></category>
		<category><![CDATA[INSERT INTO]]></category>
		<category><![CDATA[JOIN]]></category>
		<category><![CDATA[LEFT JOIN]]></category>
		<category><![CDATA[MSSQL]]></category>
		<category><![CDATA[NULL]]></category>
		<category><![CDATA[sql server]]></category>
		<category><![CDATA[UPSERT]]></category>
		<category><![CDATA[Utilità]]></category>

		<guid isPermaLink="false">http://www.dicesare.com/programmazione/sql/sql-insert-o-update-in-automatico/</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 8.9000000000006E-5 seconds-->
<!---Displayed in 0.008386 seconds.-->
Come far decidere direttamente allo script SQL se fare una INSERT o una UPDATE.

Quante volte vi sarà capitato di dover aggiornare una tabella con dei dati provenienti da una fonte esterna? Nella maggioranza dei casi, i dati da importare possono sia essere nuovi rispetto alla vostra tabella che essere degli aggiornamenti.
Scorrere con un cursore la [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 9.899999999996E-5 seconds-->
<!---Displayed in 0.005144 seconds.-->
<p>Come far decidere direttamente allo script SQL se fare una INSERT o una UPDATE.<br />
<span id="more-1022"></span><br />
Quante volte vi sarà capitato di dover aggiornare una tabella con dei dati provenienti da una fonte esterna? Nella maggioranza dei casi, i dati da importare possono sia essere nuovi rispetto alla vostra tabella che essere degli aggiornamenti.<br />
Scorrere con un cursore la tabella da importare e vedere record per record se è una novità o un aggiornamento è una scelta poco efficiente. Quale può essere allora una soluzione più performante?</p>
<h3>Sfruttare la JOIN</h3>
<p>La domanda necessaria da farsi è questa: <em>in base a quale chiave riesco a capire se un record è una novità o un aggiornamento?</em></p>
<p>Una volta trovata la risposta, il meccanismo è semplice:</p>
<ul>
<li>si metteranno in JOIN le due tabelle (da importare ed esistente) relazionandole proprio con la chiave individuata</li>
<li>la JOIN sarà una LEFT JOIN, con a sinistra la tabella da importare, e a destra quella già esistente</li>
<li>come noto, la LEFT JOIN restituirà una serie di colonne NULL nella tabella di destra nel caso non ci siano corrispondenze: sfruttando questa caratteristica potremo quindi individuare quali sono i record già esistenti e quali invece sono nuovi</li>
<li> ovviamente quelli nuovi saranno quelli con contenuto NULL, che sta a significare che i record della tabella di sinistra (da importare) <em>NON</em> sono già esistenti nella tabella di destra (esistente) e vanno quindi inseriti</li>
<li>quelli invece non-NULL sono già esistenti, e quindi andranno aggiornati</li>
<li>attenzione ad eseguire <em>PRIMA</em> la UPDATE e poi la INSERT; in caso contrario verranno aggiornati anche i record appena inseriti: i dati non vengono assolutamente danneggiati, ma sicuramente ci sarà una perdita di tempo</li>
</ul>
<h3>Esempio pratico</h3>
<p>Un esempio aiuterà a comprendere più facilmente il meccanismo.</p>
<p>Immaginiamo di dover aggiornare una tabella di Dati Anagrafici con dei dati che ci vengono inviati periodicamente da un corrispondente; in questo caso, la chiave identificativa (univoca) sarà la Partita IVA.</p>
<p>Per comodità, avremo già importato i dati del nostro corrispondente in una tabella temporanea; i nomi delle colonne saranno gli stessi.</p>
<p>Impostiamo quindi la JOIN:</p>
<pre class="brush: sql">
-- TS=TableSource, TT=TableTarget
SELECT
   TS.Descrizione, TS.PartitaIVA,
   TT.Descrizione, TT.PartitaIVA
FROM
   #tmpAnag TS LEFT JOIN ANAGRAFICHE TT ON TS.PartitaIVA=TT.PartitaIVA
</pre>
<p>Quando eseguiremo questa query, vederemo elencate delle corrispondenze esatte nel caso di record da aggiornare, mentre invece noteremo TT.Descrizione e TT.PartitaIVA a NULL nel caso di novità.</p>
<p>Sfrutteremo quindi la JOIN di riferimento per impostare prima una UPDATE&#8230;FROM&#8230;JOIN per fare gli aggiornamenti, poi una INSERT&#8230;SELECT&#8230;JOIN per fare gli inserimenti.</p>
<h3>UPDATE</h3>
<pre class="brush: sql">
-- TS=TableSource, TT=TableTarget
UPDATE ANAGRAFICHE SET
      TT.Denominazione=TS.Denominazione,
      TT.Indirizzo=TS.Indirizzo,
      TT.CAP=TS.CAP,
      TT.Localita=TS.Localita,
      TT.PartitaIVA=TS.PartitaIVA
   FROM
      #tmpAnag TS LEFT JOIN ANAGRAFICHE TT ON TS.PartitaIVA=TT.PartitaIVA
      -- fa correttamente la JOIN? Quindi c&#039;è GIA&#039;! ---&gt; UPDATE
</pre>
<h3>INSERT</h3>
<pre class="brush: sql">
-- TS=TableSource, TT=TableTarget
INSERT INTO ANAGRAFICHE
     (Denominazione,
      Indirizzo,
      CAP,
      Localita,
      PartitaIVA)
   SELECT
      TS.Denominazione,
      TS.Indirizzo,
      TS.CAP,
      TS.Localita,
      TS.PartitaIVA
   FROM
      #tmpAnag TS LEFT JOIN ANAGRAFICHE TT ON TS.PartitaIVA=TT.PartitaIVA
   WHERE TT.PartitaIVA IS NULL
   -- non fa la JOIN? Quindi NON c&#039;è! ---&gt; INSERT
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/sql-insert-o-update-in-automatico/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SQL: convertire un valore float in un varchar</title>
		<link>http://www.dicesare.com/programmazione/sql/sql-convertire-un-valore-float-in-un-varchar/</link>
		<comments>http://www.dicesare.com/programmazione/sql/sql-convertire-un-valore-float-in-un-varchar/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 23:10:11 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[2005]]></category>
		<category><![CDATA[CAST]]></category>
		<category><![CDATA[CONVERT]]></category>
		<category><![CDATA[DATA TYPE]]></category>
		<category><![CDATA[DECIMAL]]></category>
		<category><![CDATA[FLOAT]]></category>
		<category><![CDATA[NVARCHAR]]></category>
		<category><![CDATA[sql server]]></category>

		<guid isPermaLink="false">http://www.dicesare.com/programmazione/sql/sql-convertire-un-valore-float-in-un-varchar/</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.00022299999999997 seconds-->
<!---Displayed in 0.0052850000000001 seconds.-->
In questo articolo spiegherò come convertire in sicurezza una colonna float in una colonna varchar.

Mi è recentemente capitato di dover trasformare dei valori contenuti originariamente in una colonna float in un&#8217;altra colonna di tipo varchar. Il caso pratico si verifica facilmente, ad esempio con i numeri di telefono, partita iva, ecc.
La prima cosa che viene [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 8.7999999999977E-5 seconds-->
<!---Displayed in 0.0045219999999999 seconds.-->
<p>In questo articolo spiegherò come convertire in sicurezza una colonna float in una colonna varchar.<br />
<span id="more-1018"></span><br />
Mi è recentemente capitato di dover trasformare dei valori contenuti originariamente in una colonna float in un&#8217;altra colonna di tipo varchar. Il caso pratico si verifica facilmente, ad esempio con i numeri di telefono, partita iva, ecc.</p>
<p>La prima cosa che viene in mente è di effettuare una conversione diretta.</p>
<pre class="brush: sql">
ALTER TABLE nome_tabella ALTER COLUMN VARCHAR(11)
</pre>
<p>Sembra tutto corretto, ma il risultato è inaccettabile; infatti la colonna trasformata conterrà i dati con notazione scientifica. Ad esempio il numero 12345678901 diventa 1.23457e+010</p>
<p>Questo perché il formato float contiene il numero in virgola mobile, e la sua rappresentazione alfanumerica è proprio con notazione scientifica.</p>
<p>Nei casi citati abbiamo però a che fare con numeri interi (senza decimali), per cui possiamo ottenere il risultato ottenuto tramite un passaggio intermedio.</p>
<pre class="brush: sql">
ALTER TABLE nome_tabella ALTER COLUMN DECIMAL(11,0)
</pre>
<p>In questo modo abbiamo <em>fissato</em> il numero, togliendolo dalla scomoda (per il nostro fine) situazione di numero in virgola mobile.</p>
<p>A questo punto possiamo effettuare la nostra conversione:</p>
<pre class="brush: sql">
ALTER TABLE nome_tabella ALTER COLUMN VARCHAR(11)
</pre>
<p>La colonna numerica diventerà alfanumerica mantenendo il numero esattamente come ce lo aspettiamo.</p>
<p>Nell&#8217;esempio ho usato una ALTER, ma lo stesso ragionamento vale anche per le conversioni effettuate con CONVERT e CAST, come nell&#8217;esempio che segue:</p>
<pre class="brush: sql">
DECLARE @float AS FLOAT
SELECT @float=12345678901
PRINT CONVERT(VARCHAR, @float)
PRINT CONVERT(VARCHAR, CONVERT(DECIMAL(11,0), @float))
</pre>
<p>Il metodo funziona anche con NVARCHAR.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/sql-convertire-un-valore-float-in-un-varchar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL: uso di una lista di valori in una SELECT&#8230;WHERE</title>
		<link>http://www.dicesare.com/programmazione/sql/sql-uso-di-una-lista-di-valori-in-una-select-where/</link>
		<comments>http://www.dicesare.com/programmazione/sql/sql-uso-di-una-lista-di-valori-in-una-select-where/#comments</comments>
		<pubDate>Fri, 12 Feb 2010 12:38:59 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[2005]]></category>
		<category><![CDATA[ARRAY]]></category>
		<category><![CDATA[IN]]></category>
		<category><![CDATA[JOIN]]></category>
		<category><![CDATA[sql server]]></category>
		<category><![CDATA[WHERE]]></category>

		<guid isPermaLink="false">http://www.dicesare.com/programmazione/sql/sql-server-2005-uso-di-una-lista-di-valori-in-una-select-where/</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 9.0000000000034E-5 seconds-->
<!---Displayed in 0.005188 seconds.-->
In questo articolo spiegherò come effettuare una query SELECT&#8230;WHERE usando una lista di valori.

E&#8217; abbastanza comune dover effettuare delle query SQL usando una lista di valori anziché un valore singolo.
L&#8217;operatore OR
Questa operazione viene effettuata normalmente usando l&#8217;operatore OR.
Se ad esempio vogliamo selezionare i clienti che si trovano nelle provincie di Milano e Como, basterà scrivere [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 8.7000000000059E-5 seconds-->
<!---Displayed in 0.005154 seconds.-->
<p>In questo articolo spiegherò come effettuare una query SELECT&#8230;WHERE usando una lista di valori.<br />
<span id="more-934"></span><br />
E&#8217; abbastanza comune dover effettuare delle query SQL usando una lista di valori anziché un valore singolo.</p>
<h4>L&#8217;operatore <strong>OR</strong></h4>
<p>Questa operazione viene effettuata normalmente usando l&#8217;operatore OR.</p>
<p>Se ad esempio vogliamo selezionare i clienti che si trovano nelle provincie di Milano e Como, basterà scrivere una query così:</p>
<pre class="brush: sql">
SELECT
   Denominazione, Indirizzo, Localita
FROM
   Clienti
WHERE
   Provincia=&#039;MI&#039; OR Provincia=&#039;CO&#039;
</pre>
<p>L&#8217;operazione però diventa lunga e tediosa se la lista contiene molti valori: pensate infatti a cosa diventerebbe la query riportata sopra per dieci o più provincie.</p>
<h4>L&#8217;operatore <strong>IN</strong></h4>
<p>L&#8217;operatore IN dell&#8217;istruzione SELECT di SQL Server permette di semplificare notevolmente la scrittura della query.</p>
<p>Tornando al nostro esempio, per selezionare i clienti che si trovano nelle provincie di Milano e Como, basterà riscrivere la query così:</p>
<pre class="brush: sql">
SELECT
   Denominazione, Indirizzo, Localita
FROM
   Clienti
WHERE
   Provincia IN (&#039;MI&#039;,&#039;CO&#039;)
</pre>
<p>Il motore SQL elaborerà il contenuto della lista inserita tra parentesi e ri-trasformerà la query espandendo la IN in una serie di OR, per poi eseguirla normalmente.</p>
<p>Già da questo breve esempio è facile intuire quanto la stesura della query venga semplificata; e il livello di semplificazione aumenta all&#8217;aumentare degli elementi contenuti nella IN.</p>
<p>Ovviamente la stessa sintassi può essere usata anche per valori numerici.</p>
<pre class="brush: sql">
SELECT
   Denominazione, Indirizzo, Localita
FROM
   Clienti
WHERE
   Tipo IN (2,7,12,14,35,36,37)
</pre>
<h4>Uso con Stored Procedures</h4>
<p>Nascerà sicuramente la necessità di usare questa sintassi con una Stored Procedure (SP), passando i valori con un parametro.</p>
<p>Immaginiamo allora una SP così:</p>
<pre class="brush: sql">
Create Procedure usp_Cerca_Clienti (@pLista AS VARCHAR(MAX))
AS
BEGIN

   SELECT
      Denominazione, Indirizzo, Localita
   FROM
      Clienti
   WHERE
      Provincia IN (@pLista)

END
</pre>
<p>Qui iniziano subito le difficoltà, già all&#8217;atto del richiamo della SP. Avremo infatti delle difficoltà a passare il parametro; se proviamo così:</p>
<pre class="brush: sql">
EXEC usp_Cerca_Clienti @pLista=&#039;MI,CO&#039;
</pre>
<p>la SP svolta diventerà:</p>
<pre class="brush: sql">
SELECT
   Denominazione, Indirizzo, Localita
FROM
   Clienti
WHERE
   Provincia IN (&#039;MI,CO&#039;)
</pre>
<p>che ovviamente non ci darà alcun risultato (non esiste infatti la provincia &#8216;MI,CO&#8217;)</p>
<p>Se invece proviamo così:</p>
<pre class="brush: sql">
EXEC usp_Cerca_Clienti @pLista=&#039;&#039;MI&#039;,&#039;CO&#039;&#039;
</pre>
<p>riceveremo un errore di sintassi.</p>
<p>Anche con valori numerici avremo un errore; infatti se proviamo così:</p>
<pre class="brush: sql">
EXEC usp_Cerca_Clienti_per_Tipo @pLista=&#039;1,4&#039;
</pre>
<p>la SP svolta diventerà:</p>
<pre class="brush: sql">
SELECT
   Denominazione, Indirizzo, Localita
FROM
   Clienti
WHERE
   Tipo IN (&#039;1,4&#039;)
</pre>
<p>restituendoci un errore perché Tipo è una colonna numerica che non può essere raffrontata con un valore stringa.</p>
<h4>Emulare un array</h4>
<p>Certo, se SQL supportasse gli <em>array</em>, tutto sarebbe più semplice: basterebbe passare un array con i valori da usare nella IN e il gioco sarebbe fatto.</p>
<p>Per emulare il funzionamento di un array possiamo usare una variabile di tipo <em>table</em>: se la prepariamo con una sola colonna avremo emulato un array (monodimensionale).<br />
Però non possiamo usare una variabile table con l&#8217;operatore IN: dobbiamo per forza modificare la nostra SP usando una JOIN.</p>
<p>Il ragionamento diventa quindi il seguente:</p>
<ul>
<li>prepariamo una lista di valori da passare alla SP</li>
<li>i valori saranno separati da un carattere predefinito (in questo esempio useremo una virgola)</li>
<li>passiamo la lista di valori separati da virgola alla SP, in un&#8217;unica variabile</li>
<li>la SP elabora la variabile stringa e la trasforma in una variabile table, inserendo ogni valore in una riga</li>
<li>infine mette in JOIN la tabella da selezionare con la variabile table ottenuta prima ed esegue la query</li>
</ul>
<h4>Trasformazione della lista in una table</h4>
<p>La prima cosa che dovremo fare sarà quindi di trasformare la nostra lista in una variable table. Per fare questo prepareremo una funzione, così da poterla riusare tutte le volte che vogliamo.</p>
<pre class="brush: sql">
USE [master]
GO

SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO

--The following is a general purpose UDF to split comma separated lists into individual items.
--Consider an additional input parameter for the delimiter, so that you can use any delimiter you like.

-- edc 01.SEP.05
-- adattamento da http://vyaskn.tripod.com/passing_arrays_to_stored_procedures.htm
-- 

-- edc 20.sep.06
-- adattato per le stringhe

CREATE FUNCTION [dbo].[udf_CodeSplitter]
(
	@CodeList varchar(MAX)
)
RETURNS
@ParsedList table
(
	OneCode varchar(10) -- adjust the single element length to fit your needs
)
AS
BEGIN
	DECLARE @Pos int, @OneCode varchar(10) -- adjust the single element length to fit your needs

	SET @CodeList = LTRIM(RTRIM(@CodeList))+ &#039;,&#039;
	SET @Pos = CHARINDEX(&#039;,&#039;, @CodeList, 1)

	IF REPLACE(@CodeList, &#039;,&#039;, &#039;&#039;) &lt;&gt; &#039;&#039;
	BEGIN
		WHILE @Pos &gt; 0
		BEGIN
			SET @OneCode = LTRIM(RTRIM(LEFT(@CodeList, @Pos - 1)))
			IF @OneCode &lt;&gt; &#039;&#039;
			BEGIN
				INSERT INTO @ParsedList (OneCode) VALUES (@OneCode)
			END
			SET @CodeList = RIGHT(@CodeList, LEN(@CodeList) - @Pos)
			SET @Pos = CHARINDEX(&#039;,&#039;, @CodeList, 1)

		END
	END
	RETURN
END
</pre>
<p>La funzione non fa altro che selezionare i vari elementi ed inserirli in una variabile table; la tabella restituita è formata da una sola colonna (OneCode), e potrà essere messa facilmente in JOIN con la tabella da ricercare.</p>
<p>Per testare il corretto funzionamento della funzione, e per avere un&#8217;idea del risultato, basterà eseguire questa query:</p>
<pre class="brush: sql">
SELECT * FROM master.dbo.udf_CodeSplitter(&#039;MI,CO&#039;)
</pre>
<h4>La Stored Procedure finale</h4>
<p>Andremo quindi a sistemare la nostra SP così:</p>
<pre class="brush: sql">
Create Procedure usp_Cerca_Clienti (@pLista AS VARCHAR(MAX))
AS
BEGIN

   SELECT
      Denominazione, Indirizzo, Localita
   FROM
      Clienti INNER JOIN master.dbo.udf_CodeSplitter(@pLista) TJ
      ON Clienti.Provincia=TJ.OneCode

END
</pre>
<p>mettiamo cioè in JOIN la tabella Clienti con la tabella riportata dalla funzione udf_CodeSplitter, usando come campo di corrispondenza il campo della tabella Cliente dove vogliamo operare la selezione (Clienti.Provincia) e l&#8217;unico campo riportato dalla funzione (TJ.OneCode, dove <em>TJ</em> è l&#8217;alias della tabella restituita dalla funzione).</p>
<p>L&#8217;uso diventa quindi semplicissimo:</p>
<pre class="brush: sql">
exec usp_Cerca_Clienti @pLista=&#039;MI,CO&#039;
</pre>
<h4>Gestione delle liste numeriche</h4>
<p>Il ragionamento da fare per poter utilizzare delle liste numeriche resta fondamentalmente lo stesso, ma bisogna operare qualche piccola variazione per poter gestire numeri, appunto, anziché stringhe.</p>
<p>Prepareremo quindi una nuova ulteriore funzione:</p>
<pre class="brush: sql">
USE [master]
GO
/****** Object:  UserDefinedFunction [dbo].[IDSplitter]    Script Date: 02/12/2010 12:26:50 ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO

--The following is a general purpose UDF to split comma separated lists into individual items.
--Consider an additional input parameter for the delimiter, so that you can use any delimiter you like.

-- edc 01.SEP.05
-- adattamento da http://vyaskn.tripod.com/passing_arrays_to_stored_procedures.htm
-- 

ALTER FUNCTION [dbo].[udf_IDSplitter]
(
	@IDList varchar(MAX)
)
RETURNS
@ParsedList table
(
	OneID int
)
AS
BEGIN
	DECLARE @OneID varchar(10), @Pos int

	SET @IDList = LTRIM(RTRIM(@IDList))+ &#039;,&#039;
	SET @Pos = CHARINDEX(&#039;,&#039;, @IDList, 1)

	IF REPLACE(@IDList, &#039;,&#039;, &#039;&#039;) &lt;&gt; &#039;&#039;
	BEGIN
		WHILE @Pos &gt; 0
		BEGIN
			SET @OneID = LTRIM(RTRIM(LEFT(@IDList, @Pos - 1)))
			IF @OneID &lt;&gt; &#039;&#039;
			BEGIN
				INSERT INTO @ParsedList (OneID)
				VALUES (CAST(@OneID AS int)) --Use Appropriate conversion
			END
			SET @IDList = RIGHT(@IDList, LEN(@IDList) - @Pos)
			SET @Pos = CHARINDEX(&#039;,&#039;, @IDList, 1)

		END
	END
	RETURN
END
</pre>
<p>In questo caso la tabella restituita è formata da una colonna (OneID) di tipo numerico (int).</p>
<p>Per testare il corretto funzionamento della funzione, e per avere un&#8217;idea del risultato, basterà eseguire questa query:</p>
<pre class="brush: sql">
SELECT * FROM master.dbo.udf_IdSplitter(&#039;1,2,4,6,15,22&#039;)
</pre>
<p>Ricordatevi che la lista è un valore stringa, quindi va passata tra apici singoli.</p>
<h4>La Stored Procedure finale per i valori numerici</h4>
<p>Andremo quindi a sistemare la nostra SP così:</p>
<pre class="brush: sql">
Create Procedure usp_Cerca_Clienti_Tipo (@pLista AS VARCHAR(MAX))
AS
BEGIN

   SELECT
      Denominazione, Indirizzo, Localita
   FROM
      Clienti INNER JOIN master.dbo.udf_IdSplitter(@pLista) TJ
      ON Clienti.Tipo=TJ.OneId

END
</pre>
<p>In questo caso mettiamo in JOIN la tabella Clienti con la tabella riportata dalla funzione udf_IdSplitter, usando come campo di corrispondenza il campo della tabella Cliente dove vogliamo operare la selezione (Clienti.Tipo, che è di tipo int) e l&#8217;unico campo riportato dalla funzione (TJ.OneId, dove <em>TJ</em> è l&#8217;alias della tabella restituita dalla funzione).</p>
<p>L&#8217;uso diventa quindi semplicissimo:</p>
<pre class="brush: sql">
exec usp_Cerca_Clienti_Tipo @pLista=&#039;2,7,12,14,35,36,37&#039;
</pre>
<h4>Considerazioni finali</h4>
<p>Il metodo esposto semplifica notevolmente la stesura delle query di selezione basate su liste di valori. Dato che però sfrutta una funzione e una variabile table, potrebbe risultare poco performante in presenza di liste molto corpose. In questi casi potrebbe risultare più comodo popolare direttamente una tabella temporanea e metterla in JOIN con la tabella da selezionare (magari indicizzando la tabella temporanea, cosa che non può essere fatta con le variabili table).<br />
Uso il condizionale perché le performance sono influenzate da molti fattori, per cui è consigliabile effettuare delle prove caso per caso.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/sql-uso-di-una-lista-di-valori-in-una-select-where/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL: come riparare il database di sistema &#8216;msdb&#8217; danneggiato</title>
		<link>http://www.dicesare.com/programmazione/sql/sql-come-riparare-il-database-di-sistema-msdb-danneggiato/</link>
		<comments>http://www.dicesare.com/programmazione/sql/sql-come-riparare-il-database-di-sistema-msdb-danneggiato/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 12:22:07 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[2005]]></category>
		<category><![CDATA[msdb]]></category>
		<category><![CDATA[recover]]></category>
		<category><![CDATA[repair]]></category>
		<category><![CDATA[sql server]]></category>
		<category><![CDATA[system databse]]></category>

		<guid isPermaLink="false">http://www.dicesare.com/programmazione/sql/sql-server-2005-come-riparare-il-database-di-sistema-msdb-danneggiato/</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.00011499999999998 seconds-->
<!---Displayed in 0.0046240000000001 seconds.-->
Il database di sistema &#8216;msdb&#8217; di SQL Server 2005 può danneggiarsi: ecco come ripararlo.

Tra i database di sistema di Microsoft SQL Server 2005, ve ne è uno denominato &#8216;msdb&#8217; che viene usato normalmente come supporto per le pianificazioni ed altre operazioni di manutenzione o di backup.
Può accadere che si danneggi, e che di conseguenza molte [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 9.8000000000042E-5 seconds-->
<!---Displayed in 0.0046360000000001 seconds.-->
<p>Il database di sistema &#8216;msdb&#8217; di SQL Server 2005 può danneggiarsi: ecco come ripararlo.<br />
<span id="more-906"></span><br />
Tra i database di sistema di Microsoft SQL Server 2005, ve ne è uno denominato &#8216;msdb&#8217; che viene usato normalmente come supporto per le pianificazioni ed altre operazioni di manutenzione o di backup.<br />
Può accadere che si danneggi, e che di conseguenza molte operazioni diventino impossibili.<br />
Dato che non si tratta di un normale database, non può essere oggetto di normali operazioni quali <em>attach </em>e <em>detach</em>, ma bisogna seguire una procedura diversa.</p>
<table border='0'>
<tr>
<td>
<a href="http://www.dicesare.com/wp-content/uploads/important.jpg"><img src="http://www.dicesare.com/wp-content/uploads/important.jpg" alt="important" title="important" width="45" height="45" class="aligncenter size-full wp-image-918" /></a>
</td>
<td>
<blockquote><p><strong>Importante!</strong> La procedura che descriverò di seguito rigenererà il database di sistema &#8216;msdb&#8217; come appena installato, quindi tutto il suo contenuto andrà perso. Vi raccomando inoltre di effettuare il backup di tutti i dati di tutti i database dell&#8217;istanza. La procedura è riservata ad utenti esperti, e non mi assumo nessuna responsabilità; eventualmente provatelo prima su un database di test.</p></blockquote>
</td>
</tr>
</table>
<h4>1. Spegnere SQL Server</h4>
<p>Innanzitutto dovrete spegnere il servizio di SQL Server. Esistono diversi metodi; uno dei più veloci è di aprire SQL Server Management Console ed eseguire il seguente comando:</p>
<pre class="brush: sql">
SHUTDOWN
</pre>
<p>Attendete il completamento del comando ed uscite dalla console.</p>
<h4>2. Lanciare SQL Server in modalità master</h4>
<p>Per poter eseguire i comandi successivi (specificatamente per poter fare un <em>detach </em>del database &#8216;msdb&#8217;), dovrete lanciare SQL Server col trace flag 3608.<br />
Dovrete portarvi nella cartella dei programmi di SQL Server (&#8216;C:\Programmi\Microsoft SQL Server\MSSQL.1\MSSQL\Binn&#8217; per le installazioni in italiano o &#8216;C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn&#8217; per le installazioni in inglese) e lanciare il seguente comando:</p>
<pre class="brush: sql">
sqlservr.exe -c -T3608 -s &lt;NOMEISTANZA&gt;
</pre>
<p>Il comando non restituisce subito il prompt di DOS (C:>), che verrà restuituito quando SQL Server verrà nuovamente spento.</p>
<h4>3. Detach-are il database di sistema &#8216;msdb&#8217;</h4>
<p>Per detach-are il database di sistema &#8216;msdb&#8217; dovrete riaprire SQL Server Management Console, che potrebbe mostrare alcuni messaggi di avvertimento, visto che ci si trova in una modalità master.<br />
La console comunque è pronta per accettare comandi; lanciate il seguente:</p>
<pre class="brush: sql">
sp_detach_db &#039;msdb&#039;
</pre>
<p>Attendete il completamento del comando ed uscite dalla console.</p>
<h4>4. Rinominare i files del database &#8216;msdb&#8217;</h4>
<p>Ora che il database &#8216;msdb&#8217; è disconnesso, potete rinominare i files che lo costituiscono (.mdf e .ldf), che si trovano in &#8216;C:\Programmi\Microsoft SQL Server\MSSQL.1\MSSQL\Data&#8217; per le installazioni in italiano o in &#8216;C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data&#8217; per le installazioni in inglese.</p>
<h4>5. Lanciare lo script di ricostruzione</h4>
<p>Lo script di rigenerazione si trova nella cartella di installazione di SQL Server (&#8216;C:\Programmi\Microsoft SQL Server\MSSQL.1\MSSQL\Install&#8217; per le installazioni in italiano o &#8216;C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Install&#8217; per le installazioni in inglese); dopo che vi sarete portati nella cartella, lanciate il seguente comando:</p>
<pre class="brush: sql">
osql -E -S &lt;NOMESERVER&gt;\&lt;NOMEISTANZA&gt; -i instmsdb.sql
</pre>
<p>e attendete il termine delle operazioni.</p>
<h4>6. Operazioni finali</h4>
<p>La procedura è terminata. Spegnete e riaccendete normalmente SQL Server, e reinserite, se del caso, le informazioni memorizzate nel database di sistema &#8216;msdb&#8217;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/sql-come-riparare-il-database-di-sistema-msdb-danneggiato/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL: come usare l&#8217;output di una Stored Procedure SQL in una nuova Query</title>
		<link>http://www.dicesare.com/programmazione/sql/sql-come-usare-l-output-di-una-stored-procedure-sql-in-una-nuova-query/</link>
		<comments>http://www.dicesare.com/programmazione/sql/sql-come-usare-l-output-di-una-stored-procedure-sql-in-una-nuova-query/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 19:01:18 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[sp]]></category>
		<category><![CDATA[stored procedure]]></category>
		<category><![CDATA[stored procedures]]></category>

		<guid isPermaLink="false">http://www.dicesare.com/programmazione/sql/come-usare-l-output-di-una-stored-procedure-sql-in-una-nuova-query/</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.000101 seconds-->
<!---Displayed in 0.004529 seconds.-->
Avete una Stored Procedure SQL e volete usarne l&#8217;output in un&#8217;altra query (senza modificare la SP originale). Ecco come fare.

Vi sarà capitato di voler usare l&#8217;output di una Stored Procedure in un&#8217;altra query; la prima cosa che viene in mente è di modificare o duplicare la SP originale e inserire dei parametri OUTPUT, per poi [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 9.9E-5 seconds-->
<!---Displayed in 0.004962 seconds.-->
<p>Avete una Stored Procedure SQL e volete usarne l&#8217;output in un&#8217;altra query (senza modificare la SP originale). Ecco come fare.<br />
<span id="more-814"></span><br />
Vi sarà capitato di voler usare l&#8217;output di una Stored Procedure in un&#8217;altra query; la prima cosa che viene in mente è di modificare o duplicare la SP originale e inserire dei parametri OUTPUT, per poi sfruttarli.</p>
<p>Ma non sempre si <strong><em>può</em></strong>; a volte, infatti, soprattutto in ambienti complessi, certe SP non si possono toccare, perché sono usate da altre procedure o gestite da altri programmatori.</p>
<p>Cosa fare allora?</p>
<p>Supponiamo di avere una SP che mi elenca tutti i clienti di una determinata provincia</p>
<pre class="brush: sql">
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE usp_ClientiProvincia (@p_Provincia VARCHAR(2))

SET NOCOUNT ON

   SELECT CODICE, DESCRIZIONE
   FROM CLIENTI
   WHERE PROVINCIA = @p_PROVINCIA
   ORDER BY 1
</pre>
<p>una SP davvero semplice.</p>
<p>Se la facciamo girare, otteniamo due campi, CODICE e DESCRIZIONE.</p>
<p>Nella nostra nuova query dichiariamo innanzitutto una variabile TABLE che possa contenere il risultato della SP</p>
<pre class="brush: sql">
DECLARE @ClientiTable TABLE (CODICE VARCHAR(20), DESCRIZIONE VARCHAR(100))
</pre>
<p>Ovviamente la struttura della variabile varierà in base al variare dell&#8217;output della SP che volete catturare.<br />
Per memorizzare l&#8217;output della SP usiamo una comune INSERT INTO nella forma breve (INSERT INTO SELECT &#8230;), specificando anche i parameti per la SP da cattuare.</p>
<pre class="brush: sql">
INSERT INTO @ClientiTable EXEC usp_ClientiProvincia @p_PROVINCIA=&#039;MI&#039;
</pre>
<p>A questo punto ci ritroviamo nella variabile @ClientiTable l&#8217;output della SP, pronta per essere utilizzata per i nostri scopi; ad esempio:</p>
<pre class="brush: sql">
SELECT * FROM @ClientiTable WHERE DESCRIZIONE LIKE @p_cerca
</pre>
<p>Questa la query complessiva</p>
<pre class="brush: sql">
DECLARE @ClientiTable TABLE (CODICE VARCHAR(20), DESCRIZIONE VARCHAR(100))
INSERT INTO @ClientiTable EXEC usp_ClientiProvincia @p_PROVINCIA=&#039;MI&#039;
SELECT * FROM @ClientiTable WHERE DESCRIZIONE LIKE @p_cerca
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/sql-come-usare-l-output-di-una-stored-procedure-sql-in-una-nuova-query/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL: come controllare l&#8217;esistenza di un file</title>
		<link>http://www.dicesare.com/programmazione/sql/sql-come-controllare-l-esistenza-di-un-file/</link>
		<comments>http://www.dicesare.com/programmazione/sql/sql-come-controllare-l-esistenza-di-un-file/#comments</comments>
		<pubDate>Fri, 04 Sep 2009 17:28:11 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[exec]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[sp]]></category>
		<category><![CDATA[stored procedure]]></category>
		<category><![CDATA[stored procedures]]></category>
		<category><![CDATA[xp_fileexist]]></category>

		<guid isPermaLink="false">http://www.dicesare.com/?p=786</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 9.1000000000001E-5 seconds-->
<!---Displayed in 0.005019 seconds.-->
SQL Server offre la possibilità di controllare se un file esiste. Vediamo come.

Tramite una procedura interna di SQL è possibile controllare l&#8217;esistenza di un file. La procedura è xp_fileexist e va usata così

EXEC master..xp_fileexist &#039;C:\immagine.jpg&#039;

viene riportato 1 se il file esiste, oppure 0 se non esiste.
In un caso pratico ho dovuto controllare l&#8217;esistenza di un [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 8.6000000000003E-5 seconds-->
<!---Displayed in 0.004311 seconds.-->
<p>SQL Server offre la possibilità di controllare se un file esiste. Vediamo come.<br />
<span id="more-786"></span></p>
<p>Tramite una procedura interna di SQL è possibile controllare l&#8217;esistenza di un file. La procedura è <strong>xp_fileexist</strong> e va usata così</p>
<pre class="brush: sql">
EXEC master..xp_fileexist &#039;C:\immagine.jpg&#039;
</pre>
<p>viene riportato <strong>1</strong> se il file esiste, oppure <strong>0</strong> se non esiste.</p>
<p>In un caso pratico ho dovuto controllare l&#8217;esistenza di un certo numero di files, il cui nome era memorizzato in una tabella. Per fare questo, ho innanzitutto creato una funzione (udf) che effettuasse il controllo e ritornasse il flag di trovato/non trovato</p>
<pre class="brush: sql">
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:		&lt;EDC&gt;
-- Create date: &lt;05.sep.2009&gt;
-- Description:	&lt;Check file exist&gt;
-- =============================================
ALTER FUNCTION udf_FileExist
(
	@in_FileName VARCHAR(512)
)
RETURNS INT
AS
BEGIN

	DECLARE @out_result INT

	EXEC master..xp_fileexist @in_FileName, @out_result OUT

	RETURN ISNULL(@out_result,0)

END
GO
</pre>
<p>La funzione <strong>udf_FileExist</strong> accetta in input il nome del file (percorso completo) e restituisce un intero che varrà <strong>1</strong> se il file esiste, oppure <strong>0</strong> se non esiste.</p>
<p>Per usarla, sarà sufficiente richiamare la funzione nella query, così:</p>
<pre class="brush: sql">
SELECT NomeFile, dbo.udf_FileExist(NomeFile) AS Esiste FROM Tabella_Files
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/sql-come-controllare-l-esistenza-di-un-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL: come aggregare risultati diversi in un&#8217;unica riga di risultati</title>
		<link>http://www.dicesare.com/programmazione/sql/sql-come-aggregare-risultati-diversi-in-una-unica-riga-di-risultati/</link>
		<comments>http://www.dicesare.com/programmazione/sql/sql-come-aggregare-risultati-diversi-in-una-unica-riga-di-risultati/#comments</comments>
		<pubDate>Tue, 30 Jun 2009 15:50:51 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[aggregate]]></category>
		<category><![CDATA[aggregazione]]></category>
		<category><![CDATA[COUNT()]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[sp]]></category>
		<category><![CDATA[stored procedure]]></category>
		<category><![CDATA[stored procedures]]></category>

		<guid isPermaLink="false">http://www.dicesare.com/?p=772</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.000123 seconds-->
<!---Displayed in 0.005712 seconds.-->
Come aggregare risultati diversi in un&#8217;unica riga (record) di risultati
Un amico ha sollevato questo problema: come conoscere con un&#8217;unica query quante foto ha inserito un dato utente nella tabella foto e quanti blog ha inserito lo stesso utente nella tabella blogs.
Dato che il database in uso era Access, non si potevano usare Stored Procedures, quindi [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.000125 seconds-->
<!---Displayed in 0.005211 seconds.-->
<p>Come aggregare risultati diversi in un&#8217;unica riga (record) di risultati</p>
<p><span id="more-772"></span>Un amico ha sollevato questo problema: come conoscere con un&#8217;unica query quante foto ha inserito un dato utente nella tabella foto e quanti blog ha inserito lo stesso utente nella tabella blogs.</p>
<p>Dato che il database in uso era Access, non si potevano usare Stored Procedures, quindi il tutto andava fatto con un&#8217;unica query.</p>
<p>Procediamo quindi per passi successivi.</p>
<p>1. Per prima cosa vediamo come leggere quante foto sono state inserite (il nostro utente immaginario si chiamerà&#8230;. &#8220;Pippo&#8221;, come sempre)</p>
<pre class="brush: sql">
SELECT COUNT(*) FROM gallerieFoto WHERE fAutore=&quot;Pippo&quot;
</pre>
<p>il risultato della query sarà (ad esempio):<br />
<em>5</em></p>
<p>2. Adesso procediamo con la lettura di quanti messaggi sono stati inseriti nel blog</p>
<pre class="brush: sql">
SELECT COUNT(*) FROM blogs WHERE bAutore=&quot;Pippo&quot;
</pre>
<p>il risultato della query sarà (ad esempio):<br />
<em> 3</em></p>
<p>3. Ora uniamo le due query con una UNION, visto che il formato di uscita è identico</p>
<pre class="brush: sql">
SELECT COUNT(*) FROM gallerieFoto WHERE fAutore=&quot;Pippo&quot;
UNION
SELECT COUNT(*) FROM blogs WHERE bAutore=&quot;Pippo&quot;
</pre>
<p>il risultato della query sarà:<br />
<em> 5<br />
3</em></p>
<p>4. così facendo avremmo due record, ma non si vuole fare un ciclo di lettura; quindi bisogna fare in modo che la query restituisca 2 colonne, non due righe</p>
<p>5. iniziamo con l&#8217;attribuire i due nomi di colonna per i risultati: qFoto e qBlog</p>
<pre class="brush: sql">
SELECT COUNT(*) AS qFoto FROM gallerieFoto WHERE fAutore=&quot;Pippo&quot;
UNION
SELECT COUNT(*) AS qBlog FROM blogs WHERE bAutore=&quot;Pippo&quot;
</pre>
<p>il risultato della query sarà:<br />
<em>5<br />
3</em></p>
<p>6. però è ancora una colonna sola; quindi aggiungiamo una colonna per query che faccia da segnaposto: nella query delle foto aggiungiamo il segnaposto dei blog, nella query dei blog aggiungiamo il segnaposto delle foto</p>
<pre class="brush: sql">
SELECT COUNT(*) AS qFoto, 0 AS qBlog FROM gallerieFoto WHERE fAutore=&quot;Pippo&quot;
UNION
SELECT 0 as qFoto, COUNT(*) AS qBlog FROM blogs WHERE bAutore=&quot;Pippo&quot;
</pre>
<p>da notare l&#8217;inserimento incrociato dei segnaposto, per ottenere la corrispondenza delle colonne</p>
<p>il risultato della query sarà:<br />
<em>5 0<br />
0 3</em></p>
<p>7. sistemata la questione delle due colonne, resta il problema delle due righe; aggiungiamo una query esterna che raccolga i MAX delle query (infatti interessano i risultati <em>5</em> e <em>3</em>, gli zeri vanno ignorati); potremmo usare anche SUM, io per abitudine preferisco MAX.</p>
<pre class="brush: sql">
SELECT MAX(qFoto) AS qFoto, MAX(qBlog) as qBlog FROM (
SELECT COUNT(*) AS qFoto, 0 AS qBlog FROM gallerieFoto WHERE fAutore=&quot;Pippo&quot;
UNION
SELECT 0 as qFoto, COUNT(*) AS qBlog FROM blogs WHERE bAutore=&quot;Pippo&quot;
) AS subQry
</pre>
<p>il risultato della query sarà:<br />
<em>5 3</em></p>
<p>che è esattamente quello che si voleva ottenere.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/sql-come-aggregare-risultati-diversi-in-una-unica-riga-di-risultati/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL: trovare (ed eventualmente eliminare) i record duplicati</title>
		<link>http://www.dicesare.com/programmazione/sql/sql-trovare-ed-eventualmente-eliminare-i-record-duplicati/</link>
		<comments>http://www.dicesare.com/programmazione/sql/sql-trovare-ed-eventualmente-eliminare-i-record-duplicati/#comments</comments>
		<pubDate>Fri, 06 Mar 2009 17:22:15 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[doppioni]]></category>
		<category><![CDATA[duplicates]]></category>
		<category><![CDATA[duplicati]]></category>
		<category><![CDATA[exec]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[record doppi]]></category>
		<category><![CDATA[record duplicati]]></category>
		<category><![CDATA[row_number]]></category>
		<category><![CDATA[sp]]></category>
		<category><![CDATA[sql server]]></category>
		<category><![CDATA[sql server 2005]]></category>
		<category><![CDATA[stored procedure]]></category>
		<category><![CDATA[stored procedures]]></category>

		<guid isPermaLink="false">http://www.dicesare.com/programmazione/sql/trovare-ed-eventualmente-eliminare-i-record-duplicati/</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.000115 seconds-->
<!---Displayed in 0.006329 seconds.-->
In questo articolo spiegherò come selezionare (e poi eventualmente eliminare) i record duplicati di una tabella, usando SQL 2005.
Può capitare che in una tabella ci siano dei record (righe) duplicati. Rintracciarli per poi eliminarli è sempre una faccenda noisa.
Per fare questo possiamo avvalerci della funzione di numerazione righe ROW_NUMBER() di MS SQL Server 2005.
Ad esempio, questa query:

SELECT  ROW_NUMBER() [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.00012 seconds-->
<!---Displayed in 0.004594 seconds.-->
<p>In questo articolo spiegherò come selezionare (e poi eventualmente eliminare) i record duplicati di una tabella, usando SQL 2005.</p>
<p><span id="more-767"></span>Può capitare che in una tabella ci siano dei record (righe) duplicati. Rintracciarli per poi eliminarli è sempre una faccenda noisa.</p>
<p>Per fare questo possiamo avvalerci della funzione di numerazione righe ROW_NUMBER() di MS SQL Server 2005.</p>
<p>Ad esempio, questa query:</p>
<pre class="brush: sql">
SELECT  ROW_NUMBER() OVER(PARTITION BY PART_IVA ORDER BY CODICE) AS [RowNumber]
      , PART_IVA
      , CODICE
FROM  CLIENTI
</pre>
<p>elencherà tutti i Clienti, numerandoli progressivamente quando hanno la stessa Partita IVA ( &#8230; PARTITION BY PART_IVA &#8230; ).</p>
<p>Per evidenziare i duplicati, basterà aggiungere una WHERE, così</p>
<pre class="brush: sql">
SELECT * FROM (
   SELECT  ROW_NUMBER() OVER(PARTITION BY PART_IVA ORDER BY CODICE) AS [RowNumber]
         , PART_IVA
         , CODICE
   FROM  CLIENTI
   ) AS T1
WHERE RowNumber&gt;1
</pre>
<p>Similarmente, potremo usare lo stesso stratagemma per eliminare tutti i doppioni</p>
<pre class="brush: sql">
 DELETE T1 FROM (
   SELECT  ROW_NUMBER() OVER(PARTITION BY PART_IVA ORDER BY CODICE) AS [RowNumber]
         , PART_IVA
         , CODICE
   FROM  CLIENTI
   ) AS T1
  WHERE T1.RowNumber &gt;1
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/sql-trovare-ed-eventualmente-eliminare-i-record-duplicati/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SQL: COUNT inusuali</title>
		<link>http://www.dicesare.com/programmazione/sql/sql-count-inusuali/</link>
		<comments>http://www.dicesare.com/programmazione/sql/sql-count-inusuali/#comments</comments>
		<pubDate>Sat, 21 Feb 2009 17:40:46 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[COUNT()]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[sp]]></category>
		<category><![CDATA[stored procedure]]></category>
		<category><![CDATA[stored procedures]]></category>

		<guid isPermaLink="false">http://www.dicesare.com/programmazione/sql/count-inusuali/</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.00011800000000001 seconds-->
<!---Displayed in 0.00646 seconds.-->
In questo articolo illustrerò alcuni modi di usare la funzione COUNT().
La funzione COUNT() viene usata per contare (appunto) quanti record ci sono in una tabella o vista, eventualmente rispondenti ad una determinata condizione.
Ad esempio potremmo voler contare quanti clienti hanno sede a Milano.

SELECT
    COUNT(*) AS qClienti
FROM
    Clienti
WHERE
   Localita=&#039;MILANO&#039;

Potrebbe succedere però di dover riportare più conteggi; [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.000107 seconds-->
<!---Displayed in 0.005613 seconds.-->
<p>In questo articolo illustrerò alcuni modi di usare la funzione COUNT().</p>
<p><span id="more-753"></span>La funzione COUNT() viene usata per contare (appunto) quanti record ci sono in una tabella o vista, eventualmente rispondenti ad una determinata condizione.</p>
<p>Ad esempio potremmo voler contare quanti clienti hanno sede a Milano.</p>
<pre class="brush: sql">
SELECT
    COUNT(*) AS qClienti
FROM
    Clienti
WHERE
   Localita=&#039;MILANO&#039;
</pre>
<p>Potrebbe succedere però di dover riportare più conteggi; ad esempio quanti clienti hanno sede a Milano e quanti in Lombardia.</p>
<p>La prima soluzione che viene in mente è di eseguire due interrogazioni, con due WHERE diverse; si potrebbero anche riunire le due interrogazioni con una UNION, in questo modo:</p>
<pre class="brush: sql">
SELECT SUM(cMilano) AS qMilano, SUM(cLombardia) AS qLombardia FROM
   (SELECT COUNT(*) AS cMilano, 0 as cLombardia FROM Clienti WHERE Localita=&#039;MILANO&#039;
    UNION
    SELECT 0 AS cMilano, COUNT(*) AS cLombardia FROM Clienti WHERE Regione=&#039;LOMBARDIA&#039;)
</pre>
<p>Non il massimo dell&#8217;eleganza, né dell&#8217;efficienza.</p>
<p>Nella funzione COUNT possiamo però usare l&#8217;istruzione CASE, che ci permetterà di scrivere una interrogazione migliore.</p>
<p>Sfrutteremo la regola per cui i NULL non vengono contati nella COUNT; in particolare, nel nostro caso, se il risultato della WHEN è positivo (cioè corrisponde) viene restituito un risultato non-NULL, e conseguentemente contato; altrimenti (un altrimenti implicito) viene riportato NULL, che non viene contato.</p>
<pre class="brush: sql">
SELECT
   (COUNT(CASE WHEN Localita=&#039;MILANO&#039; THEN 1 END)) qMilano,
   (COUNT(CASE WHEN Regione=&#039;LOMBARDIA&#039; THEN 1 END)) qLombardia
FROM
   CLIENTI
</pre>
<p>La query è più pulita, più performante e più manutenibile. Non lasciatevi fuorviare dalla cifra &#8216;1&#8242; restituita dal CASE; un qualunque valore non-NULL va altrettanto bene (es.: <em>COUNT(CASE WHEN Localita=&#8217;MILANO&#8217; THEN &#8216;Ok!&#8217; END)</em>  )</p>
<p>Tutte le funzioni di aggregazione (COUNT, SUM, AVG, ecc.) possono essere usate in questo modo.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/sql-count-inusuali/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>LINQ SQL Dynamic</title>
		<link>http://www.dicesare.com/programmazione/sql/linq-sql-dynamic/</link>
		<comments>http://www.dicesare.com/programmazione/sql/linq-sql-dynamic/#comments</comments>
		<pubDate>Mon, 20 Oct 2008 15:04:27 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[DYNAMICLINQ2SQL]]></category>
		<category><![CDATA[DYNAMICSQL]]></category>
		<category><![CDATA[LINQ]]></category>
		<category><![CDATA[LINQ2SQL]]></category>
		<category><![CDATA[WEBGRID]]></category>

		<guid isPermaLink="false">http://www.dicesare.com/?p=400</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.00010599999999999 seconds-->
<!---Displayed in 0.004639 seconds.-->
Come aggiungere opzioni di riordinamento dinamico ad una griglia asp.net (GridView) alimentata da una sorgente dati LINQ SQL

Articolo in fase di completamento

Abbiamo una griglia asp.net (una GridView) che espone i dati di una tabella SQL; la griglia è alimentata da una sorgente dati LINQ 2 SQL che si interfaccia (ovviamente?) ad un database MS SQL [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 9.300000000001E-5 seconds-->
<!---Displayed in 0.004224 seconds.-->
<p>Come aggiungere opzioni di riordinamento dinamico ad una griglia asp.net (GridView) alimentata da una sorgente dati LINQ SQL<span id="more-400"></span></p>
<blockquote>
<p style="text-align: center;"><strong>Articolo in fase di completamento</strong></p>
</blockquote>
<p>Abbiamo una griglia asp.net (una GridView) che espone i dati di una tabella SQL; la griglia è alimentata da una sorgente dati LINQ 2 SQL che si interfaccia (ovviamente?) ad un database MS SQL 2005.</p>
<p>Il codice sorgente (HTML) della griglia sarà quindi questo:</p>
<pre class="brush: vb.net">
&lt;asp:GridView ID=&quot;grdData&quot; runat=&quot;server&quot;
   AutoGenerateColumns=&quot;false&quot;
   EmptyDataText=&quot;Nessun dato presente&quot;&gt;
   &lt;Columns&gt;
      &lt;asp:BoundField DataField=&quot;ID_AREA&quot; HeaderText=&quot;ID_Area&quot; /&gt;
      &lt;asp:BoundField DataField=&quot;Codice&quot; HeaderText=&quot;Codice&quot; /&gt;
      &lt;asp:BoundField DataField=&quot;Livello&quot; HeaderText=&quot;Livello&quot; /&gt;
      &lt;asp:BoundField DataField=&quot;Titolo&quot; HeaderText=&quot;Titolo&quot; /&gt;
   &lt;/Columns&gt;
&lt;/asp:GridView&gt;
</pre>
<p>Questa è la funzione generica di caricamento dei dati.</p>
<pre class="brush: vb.net">
Public Function GetAllCategorie() As IList(Of Categoria)
Dim dc = Factory.GetReadyDataContext()
Return (From c In dc.GetTable(Of Categoria)() Where c.STATUS = 10).ToList
End Function
</pre>
<p>La griglia così ottenuta mostrerà semplicemente i dati, senza alcuna opzione di riordinamento.</p>
<p>continua &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/linq-sql-dynamic/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL: numerare i record selezionati</title>
		<link>http://www.dicesare.com/programmazione/sql/sql-numerare-i-record-selezionati/</link>
		<comments>http://www.dicesare.com/programmazione/sql/sql-numerare-i-record-selezionati/#comments</comments>
		<pubDate>Sat, 13 Sep 2008 20:04:20 +0000</pubDate>
		<dc:creator>Enrico Di Cesare</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[row_number]]></category>
		<category><![CDATA[sp]]></category>
		<category><![CDATA[stored procedure]]></category>
		<category><![CDATA[stored procedures]]></category>

		<guid isPermaLink="false">http://lnx.dicesare.com/?p=117</guid>
		<description><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.00010500000000002 seconds-->
<!---Displayed in 0.004605 seconds.-->
In questo articolo spiegherò come far numerare i record selezionati direttamente a SQL 2005.
Una delle funzioni più richieste, e allo stesso tempo più noiose da realizzare, è la numerazione dei record selezionati con uno statement SQL. La versione 2005 di MS SQL Server include una serie di nuove funzioni che ci possono aiutare in questo senso.
La [...]]]></description>
			<content:encoded><![CDATA[<!--Searching /web/htdocs/www.dicesare.com/home/wp-content/plugins/random-image: found 4 images in 0.000107 seconds-->
<!---Displayed in 0.004426 seconds.-->
<p>In questo articolo spiegherò come far numerare i record selezionati direttamente a SQL 2005.</p>
<p><span id="more-117"></span>Una delle funzioni più richieste, e allo stesso tempo più noiose da realizzare, è la numerazione dei record selezionati con uno statement SQL. La versione 2005 di MS SQL Server include una serie di nuove funzioni che ci possono aiutare in questo senso.</p>
<p>La funzione che andremo ad utilizzare per la numerazione sarà ROW_NUMBER().</p>
<p>ROW_NUMBER (letteralmente, <em>numero di riga</em>) si usa in questo modo:</p>
<pre class="brush: sql">
SELECT
    ROW_NUMBER() OVER(ORDER BY Importo DESC) AS [RowNumber],
    CodCliente, NumeroOrdine, DataOrdine, ImportoOrdine
FROM
    Ordini
</pre>
<p>L&#8217;istruzione SELECT metterà il risultato in ordine discendente di importo (in base alla richiesta <strong>OVER(ORDER BY Importo DESC)</strong>, e numererà le righe così ottenute.</p>
<p>Il resto della SELECT è una selezione classica.</p>
<p>Questo è l&#8217;utilizzo più semplice di ROW_NUMBER(), ma è già abbastanza per farcelo apprezzare.</p>
<p>Vedremo in seguito come usare ROW_NUMBER() per</p>
<ul>
<li>numerazione a gruppi</li>
<li>estrazione di sub-set di record (simulazione della LIMIT di MySql)</li>
<li>estrazioni dei primi n record per gruppi</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.dicesare.com/programmazione/sql/sql-numerare-i-record-selezionati/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
