Биты и байты.

Биты и байты.

четверг, 26 декабря 2013 г.

Новые фичи SQL SERVER 2012 (обрывок 1)

Жизнь не стоит на месте, чтобы быть конкурентным нужно быть постоянно в движении,

видимо этому правилу и придерживаются разработчики SQL Server, посмотрим чем нас хотят удивить в  SQL SERVER 2012

и что из этого может реально принести какую-то пользу.

 

 

1. Индексы ColumnStore

Отличительная особенность колоночных индексов в том, что они основаны на колоночном хранении данных.
 
Под построчным хранением данных обычно понимается физическое хранение всей строки таблицы в виде одной записи, в которой поля идут последовательно одно за другим, а за последним полем записи в общем случае идет первое следующей записи. Приблизительно так: 
[A1, B1, C1], [A2, B2, C2], [A3, B3, C3]…
где A, B и С — это поля (столбцы), а 1,2 и 3 — номер записи (строки). 

Колоночное хранение - с точки зрения SQL-клиента данные представлены как обычно в виде таблиц, но физически эти таблицы являются совокупностью колонок, каждая из которых, по сути, представляет собой таблицу из одного поля. При этом физически на диске значения одного поля хранятся последовательно друг за другом — приблизительно так: 
[A1, A2, A3], [B1, B2, B3], [C1, C2, C3] и т.д. 
Создается как обычный индекс в SSMS или через SQL CREATE NONCLUSTERED COLUMNSTORE INDEX
Есть конечно свои  плюсы и минусы этой технологии, что не порадовало  после создания такого индекса в таблицу напрямую не внести изменения.
Операторы INSERT,UPDATE, DELETE и MERGE не поддерживаются, для обновления данных приходится пользоваться всякими извращениями . Подробно

2. Наконец-то появились последовательности SEQUENCE, тем кто  знаком с ORACLE знают какая это полезная штука.  
Например если каждый год нужно  заново нумеровать документы.

create sequence MySeq as int
       start with -- Start with value 1
       increment by 1-- Increment with value 1
       minvalue 0 -- Minimum value to start is zero
       maxvalue 100 -- Maximum it can go to 100
       no cycle -- Do not go above 100
       cache 50 -- Increment 50 values in memory rather than incrementing from

SELECT NEXT VALUE FOR dbo.MySequence AS seq_no;

3. Разбивка выборки на страницы.  OFFSET и FETCH для ограничения числа возвращаемых строк  
Если выборку необходимо вернуть порциями эта фича будет очень кстати.
Обязательно задаем порядок ORDER, смещение от начала OFFSETFETCH сколько строк нам требуется. Почитать тут.

USE AdventureWorks2012;
GO
-- Specifying variables for OFFSET and FETCH values 
DECLARE @StartingRowNumber tinyint = 1
      , @FetchRows tinyint = 8;
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC
    OFFSET @StartingRowNumber ROWS
    FETCH NEXT @FetchRows ROWS ONLY;

четверг, 19 декабря 2013 г.

Экспресс знакомство с базой SQL SERVER

Что если вам дали задание написать запрос на незнакомой базе? А времени разбираться особо нет, нет ни схемы  ни документации
Иногда спасает запрос, возвращающий семпл данных по каждому столбцу, с его помощью можно быстро определить где какие данные  



вторник, 17 декабря 2013 г.

Как подружить XML и SQL SERVER?


Как подружить XML и  таблицы SQL SERVER, все очень просто


Ниже пример кода по разбору XML тегов, с использованием оператора CROSS APPLY,
полезными будут также примеры для XPATH

  DECLARE @mytable table (RawXml XML)
      
       Insert into @mytable (RawXml)
       select N'
    <Rows>
         <Row OrderNumber="2">
             <Cell ColumnName="agrPerson" Value="77" />
             <Cell ColumnName="norma" Value="" />
             <Cell ColumnName="condition" Value="" />
             <Cell ColumnName="denyDelete" Value="false" />
             <Cell ColumnName="denyMove" Value="false" />
             <Cell ColumnName="denyAdd" Value="" />
             <Cell ColumnName="controlTerm" Value="true" />
<level1>
<tags>
<tag>Green</tag>
<tag>Sams</tag>
<tag>Grass</tag>
</tags>
<level2> </level2>
</level1>
         </Row>
         <Row OrderNumber="3">
             <Cell ColumnName="agrPerson" Value="80" />
             <Cell ColumnName="norma" Value="" />
             <Cell ColumnName="condition" Value="" />
             <Cell ColumnName="denyDelete" Value="false" />
             <Cell ColumnName="denyMove" Value="false" />
             <Cell ColumnName="denyAdd" Value="" />
             <Cell ColumnName="controlTerm" Value="true" />
         </Row>
       </Rows>'

    SELECT
                    x.XmlCol.value('@ColumnName', 'nvarchar(255)') AS ColumnName,
                    x.XmlCol.value('@Value', 'nvarchar(255)') AS Value     
     FROM  @mytable b
       CROSS APPLY b.RawXml.nodes('/Rows/Row/Cell') x(XmlCol)

Более сложный вариант с вложенными элементами

  SELECT
                    row.value('@OrderNumber', 'nvarchar(255)') AS OrderNum,
                    tags.value('.', 'nvarchar(255)') tag,
                    tags.query('.') t     
     FROM  @mytable b
       CROSS APPLY RawXml.nodes('/Rows/Row') AS row( row )
       outer apply row.nodes('level1/tags/tag') tags(tags);



Есть другой вариант с использованием инструкции  OPENXML

среда, 11 декабря 2013 г.

Qlikview основы

Небольшая памятка по работе с Qlik.
1.Загружаем данные, создаем новый файл жмем  Ctrl+E, или редактор скрипта
2. Подготавливаем данные для внутренней модели пишем загрузочный скрипт
Модель создается автоматически по одноименным полям.   Поэтому переименовываем в источнике  или с помощью  псевдонимов AS
Проверить модель можно нажав Ctrl + T

Самый простой пример скрипта по загрузке на примере файлов QVD

///$tab Main
SET ThousandSep=',';
SET DecimalSep='.';
SET MoneyThousandSep=',';
SET MoneyDecimalSep='.';
SET MoneyFormat='$#,##0.00;($#,##0.00)';
SET TimeFormat='h:mm:ss TT';
SET DateFormat='M/D/YYYY';
SET TimestampFormat='M/D/YYYY h:mm:ss[.fff] TT';
SET MonthNames='Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec';
SET DayNames='Mon;Tue;Wed;Thu;Fri;Sat;Sun';

//=========================================================

LET vTodaysDate = num(Makedate(Year(today()), 6, 30));
LET vAdj =  $(vTodaysDate) - Makedate(2004, 6, 30);



///$tab Mapping
ProductCostMap:
MAPPING LOAD DISTINCT
                ProductID,
    StandardCost
FROM
                ProductCostMap.QVD (qvd)
;

///$tab Orders
OrderHeader:
Load
                SalesOrderID,
    RevisionNumber,
    Date(OrderDate + $(vAdj)) as OrderDate,
    Date(DueDate + $(vAdj)) as DueDate,
    Date(ShipDate + $(vAdj)) as ShipDate,
    Status,
    OnlineOrderFlag,
    SalesOrderNumber,
    PurchaseOrderNumber,
    AccountNumber,
    CustomerID,
    ContactID,
    SalesPersonID,
    TerritoryID,
    BillToAddressID,
    ShipToAddressID,
    ShipMethodID,
    CreditCardID,
    CreditCardApprovalCode,
    CurrencyRateID,
    SubTotal,
    TaxAmt,
    Freight,
    TotalDue,
    Comment
FROM
                OrderHeader.QVD (qvd)
WHERE
                OrderDate + $(vAdj) <= $(vTodaysDate) and Year(OrderDate + $(vAdj)) >= Year($(vTodaysDate)) - 2
;



[Order Detail]:
LOAD
                SalesOrderID,
    SalesOrderDetailID,
    CarrierTrackingNumber,
    OrderQty,
    ProductID,
    SpecialOfferID,
    UnitPrice,
    UnitPriceDiscount,
    LineTotal as SalesAmount,
                LineTotal - (ApplyMap('ProductCostMap', ProductID, 1)*OrderQty) as MarginAmount,
    ApplyMap('ProductCostMap', ProductID, 1) as CostAmount
FROM
                OrderDetail.QVD (qvd)
WHERE
                EXISTS(SalesOrderID)
;

///$tab Calendar
Calendar:
LOAD DISTINCT
                OrderDate,
                Year(OrderDate) as Year,
                Month(OrderDate) as Month,
                Date(Monthstart(OrderDate), 'MMM-YYYY') as YearMonth,
                'Q' & Ceil(Month(OrderDate)/3) as Quarter,
                Dual(Year(OrderDate) & '-Q' & Ceil(Month(OrderDate)/3), Year(OrderDate) & Ceil(Month(OrderDate)/3)) as YearQtr,
                Week(OrderDate) as Week
RESIDENT
                OrderHeader;  
///$tab Products
Product:
LOAD
                ProductID,
    Name as ProductName,
    ProductNumber & ' : ' & Name as Product,
    ProductNumber,
    MakeFlag,
    FinishedGoodsFlag,
    Color,
    SafetyStockLevel,
    ReorderPoint,
    StandardCost,
    ListPrice,
    Size,
    SizeUnitMeasureCode,
    WeightUnitMeasureCode,
    Weight,
    DaysToManufacture,
    ProductLine,
    Class,
    Style,
    ProductSubcategoryID,
    ProductModelID,
    SellStartDate,
    SellEndDate,
    DiscontinuedDate
FROM
                Product.QVD (qvd)
WHERE
                EXISTS(ProductID)
;



ProductSubCategory:
LOAD
                ProductSubcategoryID,
    Name as ProductSubcategoryName,
    ProductCategoryID
FROM
                ProductSubCategory.QVD (qvd)
WHERE
                EXISTS(ProductSubcategoryID)
;



ProductCategory:
LOAD
                ProductCategoryID,
    Name as ProductCategoryName
FROM
                ProductCategory.QVD (qvd)
WHERE
                EXISTS(ProductCategoryID)
;



///$tab Customer
Customer:
LOAD
                CustomerID,
                LastName & ', ' & FirstName as CustomerName,
                CustomerID & ' - ' & LastName & ', ' & FirstName as Customer,
                Phone,
    EmailAddress,
    EmailPromotion,
    Title
FROM
                Customer.QVD (qvd)
WHERE
                EXISTS(CustomerID)
;


vIndividualDemographics:
LOAD
                CustomerID,
    TotalPurchaseYTD,
    DateFirstPurchase,
    Date(BirthDate) as BirthDate,
    MaritalStatus,
    YearlyIncome,
    Gender,
    if(TotalChildren > 0, 'YES', 'NO') as [Have Child(ren)],
    TotalChildren,
    NumberChildrenAtHome,
    Education,
    Occupation,
    HomeOwnerFlag,
    NumberCarsOwned
FROM
                vIndividualDemographics.QVD (qvd)
WHERE
                EXISTS(CustomerID)
;


[Customer Type]:
Load
                CustomerID,
                if(CustomerType = 'S','STORE',if(CustomerType='I', 'INDIVIDUAL', CustomerType)) as CustomerType
FROM
                CustomerType.QVD (qvd)
WHERE
                EXISTS(CustomerID)
;


BillToAddress:
LOAD
                BillToAddressID,
                AddressLine1,
                AddressLine2,
                City,
                StateProvinceID,
                PostalCode,
                CountryRegionCode,
                [State / Province],
                Country
FROM
                BillToAddress.QVD (qvd)
WHERE
                EXISTS(BillToAddressID)
;

               


вторник, 10 декабря 2013 г.

Что делать если вас не узнают в SSRS?

Что делать если вас не узнают в Reporting Services или добро пожаловать ANONYMOUS….


Если у вас  например трехзвенная архитектура (клиент-> сервер приложений/отчетов-> сервер реляционной/многомерной БД) и  вы пользуетесь авторизацией Windows
Вы точно столкнетесь с этой задачей, однако на практике она оказывается гораздо проще чем кажется..
при запуске отчета по раздаче прав, который берет  данные с   сервера БД , возникла ошибка

Т.к. здесь возникает второй круг авторизации, первый от клиента к серверу отчетов, второй  от сервера отчетов к серверу БД, схема приблизительно выглядит так

Для решения этой задачи в принципе достаточно настроить авторизацию по протоколу Kerberos,
для этого нужно зарегистрировать в Active Directory  SPN (Service Principal Name) для учетной записи под которой работает сервис  и в итоге получится
Благодаря сопоставлению SPN, определенному в Active Directory (AD), учетная запись Windows, ответственная за службу,
может быть удостоверена и использована для проверки подлинности Kerberos

Вкратце о типах проверки подлинности в Reporting Services можно прочитать здесь

пятница, 6 декабря 2013 г.

Публикация отчетов SSRS на Sharepoint

Сделал ты например  отчет и чего с ним делать , хочется же все же поделиться им с  человеками ..
Вроде все просто когда сервер отчетов настроен в режиме Native Mode.
Но хочется же большего чтобы прямо на корпоративный портал и все заходили и пользовались.
Понадобится всего пару телодвижений.
Заходим на наш сайт в Sharepoint 2010

Создаем там 2 библиотеки документов, одна библиотека Reports будет для самих отчетов, другая под источники данных Report Data Sources
Выбираем элемент библиотека документов, называем ее Reports


Итеграция SharePoint 2010 и SSRS 2008

Интеграция, без нее никуда сейчас, с ней все вдруг становится простым и удобным. А кто против интеграции тот не вступит в Евросоюз))

Сегодня рассмотрим интеграцию двух  интересных продуктов SharePoint 2010 и Reporting Services 2008 из комплекта SQL SERVER 2008 R2.
Допустим у нас уже есть установленные  SharePoint 2010  и SQL SERVER 2008 как установить эти программы можно почитать отдельно.
1.Все начинается с того что нужно сконфигурировать Reporting Services 2008 в режим интеграции с SharePoint 2010  через  Reporting Services Configuration Manager,
Открывается через пуск-> программы-> SQL SERVER 2008  R2


вторник, 3 декабря 2013 г.

Регулярные выражения (REGEXP)

Если у вас есть проблема, и вы собираетесь её решать с помощью регулярных выражений, тогда у вас будет уже две проблемы...

^[-.\w]+@(?:[a-z\d]{2,}\.)+[a-z]{2,6}$     прям так сходу и не скажешь, что проверяет этот шаблон,  кому интересно найдут подсказку дальше

Картинки по запросу regexp

Регулярные выражения это способ записи некоего шаблона  по которому мы будем проверять есть ли подобная хрень в тексте или нет,  с их помощью можно парсить (разбирать) любые html страницы. Полное описание  символов можно найти на сайте М

Главное это служебные символы, по ссылке полный список служебных символов  Regexp.net , вкратце  рассмотрим основные символы и шаблоны поиска

1.  [abcd] находит любой элемент из группы  :  This is a regexp test abc is not bca
2.  [0-6] находит любой элемент из диапазона : сколько будет 6 на 8 = 48
3.  be|not  находит либо одно либо другое, работает как или : to be or  not to be
4.  n.t , точка заменяет любой одиночный символ : not this is a nut test
5.  .*? любой текст между  символами например <.*?> : not this is <html tag> a nut test
6. [-#'!""£$%^&*()\\]+? удаляет спец символы Jack is "Supafly" £$% + Mike = : Reverse

\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\> этот шаблон находит комменты<!-- comment -->

Протестировать шаблон всегда можно по ссылке , для шаблона сверху можно проверить текст  wtf@email.com

Вроде ничего сложного, но бывает непросто разобрать кучу этих иероглифов)))

И в качестве бонуса…

Будь выше любых иерархий!

Везде куда  не глянь, есть иерархии,  в армии, на работе, в жизни и быту,
так уж устроен мир одни управляют другими……


Допустим нужно вывести иерархический справочник в виде списка чтобы визуально было понятно кто кому зачем и почему)
для этого нужна простая иерархия родитель-потомок, построим на примере сотрудников, здесь ID потомок, MgrID родитель.
Самыми главными будем считать тех у кого нет босов т. е  WHERE MgrID IS NULL

About